89 votes

Erreur de programmation : Les objets SQLite créés dans un thread ne peuvent être utilisés que dans ce même thread.

Je suis assez novice en matière de programmation. J'ai déjà essayé MySQL, mais c'est la première fois que j'utilise SQLite dans un site web python flask. Peut-être que j'utilise la syntaxe MySQL au lieu de SQLite, mais je n'arrive pas à trouver le problème.

Piece of my code: 

@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm(request.form)
    if request.method=='POST' and form.validate():
        name =  form.name.data 
        email = form.email.data
        username = form.username.data
        password = sha256_crypt.encrypt(str(form.password.data))

        c.execute("INSERT INTO users(name,email,username,password) 
        VALUES(?,?,?,?)", (name, email, username, password))

        conn.commit

        conn.close()

The error:
 File "C:\Users\app.py", line 59, in register c.execute("INSERT INTO users(name,email,username,password) VALUES(?,?,?,?)", (name, email, username, password))
 ProgrammingError: SQLite objects created in a thread can only be used in that 
 same thread.The object was created in thread id 23508 and this is thread id 
 22640

Cela signifie-t-il que je ne peux pas utiliser le nom, l'adresse électronique et le mot de passe dans un fichier HTML ? Comment puis-je résoudre ce problème ?

Merci.

2 votes

Non, ce sont clairement des objets python définis juste au-dessus. Le message d'erreur parle de la connexion et du curseur.

121voto

cmrussell Points 534

Lorsque vous établissez votre connexion à la base de données, ajoutez ce qui suit.

conn = sqlite3.connect('your.db', check_same_thread=False)

44 votes

L'utilisation de ce produit est-elle sûre ?

4 votes

@uzu, je ne vois pas pourquoi pas, tant que vous faites votre propre synchronisation pour vous assurer qu'un seul thread utilise l'objet en même temps.

19 votes

Quelques informations supplémentaires pour les futurs lecteurs de ce fil. Par docs.python.org/3/library/sqlite3.html : Par défaut, check_same_thread est True et seul le thread créateur peut utiliser la connexion. Si la valeur est False, la connexion retournée peut être partagée entre plusieurs threads. Lors de l'utilisation de plusieurs threads avec la même connexion, les opérations d'écriture doivent être sérialisées par l'utilisateur pour éviter la corruption des données.

52voto

m1ke Points 269

Votre curseur 'c' n'est pas créé dans le même thread ; il a probablement été initialisé lors de l'exécution de l'application Flask.

Vous souhaitez probablement générer les objets SQLite (la connexion et le curseur) de la même manière, par exemple :

  @app.route('/')
  def dostuff():
    with sql.connect("database.db") as con:
      name = "bob"
      cur = con.cursor()
      cur.execute("INSERT INTO students (name) VALUES (?)",(name))
      con.commit()
      msg = "Done"

2 votes

Je suis tombé sur ce problème. Je suis en train de suivre un cours de développement complet d'udacity qui semble contenir des éléments de python2. Donc c'est en fait une bonne opportunité d'apprentissage. L'une ou l'autre méthode a fonctionné pour moi. J'avais ce qui suit en haut du fichier app.py et puis j'ai littéralement copié et collé dans cette fonction (chemin) et voilà, le problème est résolu. python DBSession = sessionmaker(bind=engine) session = DBSession()

1 votes

Faut-il aussi un con.close() ou est-ce que le with s'occuper de ça ?

41voto

J J Points 101
engine = create_engine(
'sqlite:///restaurantmenu.db',
connect_args={'check_same_thread': False}
)

Cela fonctionne pour moi

3 votes

Bonjour J J, bienvenue sur Stack Overflow ! Pouvez-vous améliorer cette réponse ? Utilisez les guillemets simples ` pour montrer le code comme ce `code`, et expliquez pourquoi le code en question répond à la question/fait le travail que la personne a demandé

1 votes

Merci, ajouter les args au moteur a parfaitement fonctionné pour moi.

6voto

ng10 Points 371

Dans mon cas, j'ai le même problème avec deux fichiers python qui créent un moteur sqlite et qui, par conséquent, fonctionnent peut-être sur des threads différents. Lecture de la doc SQLAlchemy aquí il semble qu'il soit préférable d'utiliser la technique du singleton dans les deux fichiers :

# maintain the same connection per thread
from sqlalchemy.pool import SingletonThreadPool
engine = create_engine('sqlite:///mydb.db',
                poolclass=SingletonThreadPool)

Cela ne résout pas tous les cas, ce qui signifie que j'obtiens occasionnellement la même erreur, mais je peux facilement la surmonter, en rafraîchissant la page du navigateur. Comme je ne l'utilise que pour déboguer mon code, cela me convient. Pour une solution plus permanente, vous devriez probablement choisir une autre base de données, comme PostgreSQL ou une autre base de données.

5voto

Asgar Points 116

Vous pouvez essayer ceci :

engine=create_engine('sqlite:///data.db', echo=True, connect_args={"check_same_thread": False})

Cela a marché pour moi

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X