私はこのようなことをしています...
_conn = sqlite3.connect(db_filename)
with conn:
cur = conn.cursor()
cur.execute( ... )
_
with
は自動的に変更をコミットします。しかし、ドキュメントは接続を閉じることについて何も述べていません。
実際、後のステートメント(テスト済み)でconn
を使用できます。したがって、コンテキストマネージャは接続を閉じていないようです。
接続を手動で閉じる必要がありますか。開いたままにするとどうなりますか?
[〜#〜] edit [〜#〜]
私の発見:
__exit__
_が発生すると、コンテキストマネージャはconn.commit()
を実行することによってのみ変更をコミットしますwith conn
_とwith sqlite3.connect(db_filename) as conn
は同じなので、どちらを使用しても接続は維持されますwith
ステートメントは新しいスコープを作成しません。したがって、withのスイート内で作成されたすべての変数は、その外部からアクセス可能です。SQLiteデータベースを閉じない場合に何が起こるかという特定の質問への回答では、答えは非常に簡単で、あらゆるプログラミング言語でSQLiteを使用する場合に当てはまります。接続がコードによって明示的に閉じられるか、プログラム出口によって暗黙的に閉じられると、未処理のトランザクションはロールバックされます。 (実際にロールバックは、データベースを開く次のプログラムによって実行されます。)開いている未処理のトランザクションがない場合、何も起こりません。
これは、プロセスを終了する前にデータベースを常に閉じることについてあまり心配する必要がなく、トランザクションを開始して適切な時点でコミットするように注意する必要があることを意味します。
ここには根本的な懸念がありますが、sqliteの動作も理解することも重要です。
_1. connection open
2. transaction started
3. statement executes
4. transaction done
5. connection closed
_
データの正確さに関しては、ハンドルを開くのではなく、トランザクションのみを心配する必要があります。 sqliteは、トランザクション(*)またはステートメントの実行内でのみデータベースのロックを保持します。
ただし、リソース管理の観点からsqliteファイルを削除するか、ファイル記述子を使い果たす可能性がある非常に多くの接続を使用する予定がある場合は、開いているトランザクション外の接続も気にします。
接続を閉じるには2つの方法があります:.close()
を明示的に呼び出した後、ハンドルはまだあるが使用できないか、接続をスコープから外してガベージコレクションを取得します。
接続を閉じる必要があるの場合、Pythonのモットー「明示的は暗黙的より良い」に従って明示的に閉じます。
コードの副作用のみをチェックしている場合、接続への参照を保持している最後の変数をスコープ外にすることは許容できますが、例外はスタックをキャプチャし、そのスタック内の参照をキャプチャすることに注意してください。例外を渡すと、接続の有効期間が任意に延長される場合があります。
警告プログラム、sqliteはデフォルトで「遅延」トランザクションを使用します。つまり、トランザクションはステートメントの実行時にのみ開始されます。上記の例では、トランザクションは2〜4ではなく3〜4で実行されます。
これは私が使用するコードです。 Connection
とCursor
は、contextlib.closing()
のおかげで自動的に閉じます。 Connection
は、コンテキストマネージャーのおかげで自動的にコミットされます。
import sqlite3
import contextlib
def execute_statement(statement):
with contextlib.closing(sqlite3.connect(path_to_file)) as conn: # auto-closes
with conn: # auto-commits
with contextlib.closing(conn.cursor()) as cursor: # auto-closes
cursor.execute(statement)
次のようなwith
ブロックを使用できます。
from contextlib import closing
import sqlite3
def query(self, db_name, sql):
with closing(sqlite3.connect(db_name)) as con, con, \
closing(con.cursor()) as cur:
cur.execute(sql)
return cur.fetchall()
幸せな場合と例外的な場合の両方ですべて安全
ご使用のバージョンは、接続の使用後にconnをスコープ内に残します。
例:
バージョン
conn = sqlite3.connect(db_filename) #DECLARE CONNECTION OUT OF WITH BLOCK
with conn: #USE CONNECTION IN WITH BLOCK
cur = conn.cursor()
cur.execute( ... )
#conn variable is still in scope, so you can use it again
新しいバージョン
with sqlite3.connect(db_filename) as conn: #DECLARE CONNECTION AT START OF WITH BLOCK
cur = conn.cursor()
cur.execute( ... )
#conn variable is out of scope, so connection is closed
# MIGHT BE IT IS NOT CLOSED BUT WHAT Avaris SAID!
#(I believe auto close goes for with block)
データベースへの接続を管理するには、通常これを行いますが、
# query method belonging to a DB manager class
def query (self, sql):
con = sqlite3.connect(self.dbName)
with con:
cur = con.cursor()
cur.execute(sql)
res = cur.fetchall()
if con:
con.close()
return res
そうすることで、接続が明示的に閉じられると確信しています。