Programming Error: 스레드에서 생성된 SQLite 개체는 동일한 스레드에서만 사용할 수 있습니다.
프로그래밍은 처음이라서요MySQL을 사용해 본 적은 있지만, Python Flask 웹사이트에서 SQLite를 사용하는 것은 처음입니다.SQLite 대신 MySQL 구문을 사용하지만 문제를 찾을 수 없습니다.
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
이름, 이메일 사용자 이름, 비밀번호를 HTML 파일로 사용할 수 없는 건가요?이거 어떻게 풀어요?
감사해요.
데이터베이스에 연결할 때 다음을 추가합니다.
conn = sqlite3.connect('your.db', check_same_thread=False)
커서 'c'는 같은 스레드에 생성되지 않습니다.아마 Flask 앱 실행 시 초기화되었을 것입니다.
다음과 같은 동일한 방법으로 SQLite 개체(conneciton 및 커서)를 생성할 수 있습니다.
@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"
engine = create_engine(
'sqlite:///restaurantmenu.db',
connect_args={'check_same_thread': False}
)
효과가 있다
다음과 같이 시험해 보십시오.
engine=create_engine('sqlite:///data.db', echo=True, connect_args={"check_same_thread": False})
그것은 나에게 효과가 있었다.
제 경우, sqlite 엔진을 생성하는 두 개의 python 파일에 동일한 문제가 있으며, 따라서 다른 스레드로 동작할 수 있습니다.SQL Chemy 문서를 읽으면 두 파일 모두에서 싱글톤 기술을 사용하는 것이 더 나을 것 같습니다.
# maintain the same connection per thread
from sqlalchemy.pool import SingletonThreadPool
engine = create_engine('sqlite:///mydb.db',
poolclass=SingletonThreadPool)
모든 케이스가 해결되는 것은 아닙니다.즉, 같은 에러가 발생하는 경우가 있습니다만, 간단하게 극복할 수 있어 브라우저 페이지를 갱신할 수 있습니다.코드를 디버깅하기 위해서만 사용하고 있기 때문에, 이것으로 괜찮습니다.보다 영속적인 솔루션을 이용하려면 Postgre와 같은 다른 데이터베이스를 선택해야 합니다.SQL 또는 기타 데이터베이스
같은 문제가 발생하여 콜이 끝날 때마다 접속을 종료하여 해결했습니다.
results = session.query(something, something).all()
session.close()
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)
대로 삽입되어 여전히 while
loopsyslog.syslog..syslog.
- https://docs.python.org/3/library/queue.html
- https://docs.python.org/3/library/threading.html#threading.Thread.join
- https://docs.python.org/3/library/threading.html#threading.get_ident
이 오류는 에서 호출된 변수에는 없습니다..execute()
SQLite가 DB에 액세스하기 위해 사용하는 객체 인스턴스입니다.
다음 사항이 있을 것으로 생각합니다.
conn = sqlite3.connect('your_database.db')
c = conn.cursor()
이 스크립트는 처음 실행할 때 초기화됩니다.
언제?register
함수를 호출하면 처음 실행한 스크립트와는 다른 새 스레드가 프로세스를 처리합니다.따라서 이 새로운 스레드에서는 SQLite가 오류로 캡처한 다른 스레드의 오브젝트 인스턴스를 사용하고 있습니다.이러한 인스턴스는 앱 실행 중에 다른 스레드에서 DB에 액세스할 것으로 예상할 경우 데이터가 손상될 수 있기 때문입니다.
따라서 다른 방법으로 동일한 스레드 SQLite 체크 기능을 비활성화하는 대신 호출되는 HTTP 메서드 내에서 DB 연결 및 커서를 초기화해 볼 수 있습니다.
이를 통해 SQLite 객체와 사용률은 런타임에 동일한 스레드 상에 있게 됩니다.
코드는 장황하지만, 데이터에 비동기적으로 액세스 하고 있는 상황에서는 데이터를 보호할 수 있을 뿐만 아니라 데이터의 파손도 방지할 수 있습니다.
안녕하세요?sqlite3에서도 같은 문제가 발생했어요!
- 나는 그 오류를 이용하여 이 문제를 해결했다.
database.py 파일을 만들었습니다.
-그리고 나는 썼다.
import sqlite3
def dbcon():
db = sqlite3.connect("your.db")
cur = db.cursor()
return cur
그럼 사용하려는 곳에서 가져오기만 하면 됩니다.
from database import dbcon
db = dbcon()
db.execute("INSERT INTO users(name,email,username,password)
VALUES(?,?,?,?)", (name, email, username, password))
스레드가 바로 끊어지기 때문에 닫을 필요가 없을지도 모릅니다.포옹! :)
언급URL : https://stackoverflow.com/questions/48218065/programmingerror-sqlite-objects-created-in-a-thread-can-only-be-used-in-that-sa
'programing' 카테고리의 다른 글
Matplotlib에서 선의 개별 점에 대한 표식기 설정 (0) | 2023.01.10 |
---|---|
C 프리프로세서에서 Mac OS X, iOS, Linux, Windows를 신뢰성 있게 검출하는 방법 (0) | 2023.01.10 |
문자열에서 utf8이 아닌 문자 제거 (0) | 2023.01.10 |
mysql에 한 테이블에서 다른 테이블로 데이터를 삽입합니다. (0) | 2023.01.10 |
파일의 선두에서 「」를 삭제하려면 어떻게 해야 합니까? (0) | 2023.01.10 |