Tan*_*nia 33 python mysql sqlite flask
我对编程很新.我之前尝试过MySQL,但现在我第一次在python烧瓶网站上使用SQLite了.所以也许我使用MySQL语法而不是SQLite,但我似乎无法找到问题.
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
Run Code Online (Sandbox Code Playgroud)
这是否意味着我不能在HTML文件中使用名称,电子邮件用户名和密码?我该如何解决这个问题?
谢谢.
小智 41
在与数据库建立连接的位置添加以下内容.
conn = sqlite3.connect('your.db', check_same_thread=False)
Run Code Online (Sandbox Code Playgroud)
ndr*_*rix 22
你的光标'c'不是在同一个线程中创建的; 它可能是在运行Flask应用程序时初始化的.
您可能希望以相同的方法生成SQLite对象(连接和光标),例如:
@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"
Run Code Online (Sandbox Code Playgroud)
小智 10
engine = create_engine(
'sqlite:///restaurantmenu.db',
connect_args={'check_same_thread': False}
)
Run Code Online (Sandbox Code Playgroud)
为我工作
小智 8
你可以试试这个:
engine=create_engine('sqlite:///data.db', echo=True, connect_args={"check_same_thread": False})
Run Code Online (Sandbox Code Playgroud)
这对我有用
就我而言,我在创建 sqlite 引擎的两个 python 文件中遇到了同样的问题,因此可能在不同的线程上运行。在此处阅读 SQLAlchemy 文档,似乎在两个文件中都使用单例技术更好:
# maintain the same connection per thread
from sqlalchemy.pool import SingletonThreadPool
engine = create_engine('sqlite:///mydb.db',
poolclass=SingletonThreadPool)
Run Code Online (Sandbox Code Playgroud)
它不能解决所有情况,这意味着我偶尔会遇到相同的错误,但我可以轻松克服它,刷新浏览器页面。因为我只用它来调试我的代码,所以这对我来说没问题。对于更永久的解决方案,应该选择另一个数据库,如 PostgreSQL 或其他数据库
正如https://docs.python.org/3/library/sqlite3.html中提到的,并由 @Snidhi Sofpro 在评论中指出
默认情况下,check_same_thread 为 True,并且只有创建线程可以使用该连接。如果设置为 False,则返回的连接可以在多个线程之间共享。当使用具有相同连接的多个线程时,用户应将写入操作序列化,以避免数据损坏。
实现序列化的一种方法:
import threading
import sqlite3
import queue
import traceback
import time
import random
work_queue = queue.Queue()
def sqlite_worker():
con = sqlite3.connect(':memory:', check_same_thread=False)
cur = con.cursor()
cur.execute('''
CREATE TABLE IF NOT EXISTS test (
id INTEGER PRIMARY KEY AUTOINCREMENT,
text TEXT,
source INTEGER,
seq INTEGER
)
''')
while True:
try:
(sql, params), result_queue = work_queue.get()
res = cur.execute(sql, params)
con.commit()
result_queue.put(res)
except Exception as e:
traceback.print_exc()
threading.Thread(target=sqlite_worker, daemon=True).start()
def execute_in_worker(sql, params):
# you might not really need the results if you only use this
# for writing unless you use something like https://www.sqlite.org/lang_returning.html
result_queue = queue.Queue()
work_queue.put(((sql, params), result_queue))
return result_queue.get(timeout=5)
def insert_test_data(seq):
time.sleep(random.randint(0, 100) / 100)
execute_in_worker(
'INSERT INTO test (text, source, seq) VALUES (?, ?, ?)',
['foo', threading.get_ident(), seq]
)
threads = []
for i in range(10):
thread = threading.Thread(target=insert_test_data, args=(i,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
for res in execute_in_worker('SELECT * FROM test', []):
print(res)
# (1, 'foo', 139949462500928, 9)
# (2, 'foo', 139949496071744, 5)
# (3, 'foo', 139949479286336, 7)
# (4, 'foo', 139949487679040, 6)
# (5, 'foo', 139949854099008, 3)
# (6, 'foo', 139949470893632, 8)
# (7, 'foo', 139949862491712, 2)
# (8, 'foo', 139949845706304, 4)
# (9, 'foo', 139949879277120, 0)
# (10, 'foo', 139949870884416, 1)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,数据是乱序插入的,但仍然是在循环中一一处理while。