2012-03-05 41 views
42

Tôi đang làm một cái gì đó như thế này ...gì nếu tôi không đóng kết nối cơ sở dữ liệu SQLite bằng Python

conn = sqlite3.connect(db_filename) 

with conn: 
    cur = conn.cursor() 
    cur.execute(...) 

with tự động cam kết những thay đổi. Nhưng các tài liệu không nói gì về việc đóng kết nối.

Thực ra tôi có thể sử dụng conn trong các phát biểu sau (mà tôi đã thử nghiệm). Do đó có vẻ như người quản lý ngữ cảnh KHÔNG đóng kết nối.

Tôi có phải đóng kết nối theo cách thủ công không. Nếu tôi để nó mở thì sao?

EDIT

kết luận của tôi ...

  • Kết nối KHÔNG đóng trong bộ quản lý bối cảnh, tôi đã thử nghiệm và xác nhận nó. Khi __exit__, người quản lý ngữ cảnh CHỈ cam kết các thay đổi bằng cách thực hiện conn.commit()
  • with connwith sqlite3.connect(db_filename) as connmột và cùng một điều. Vì vậy, sử dụng một trong hai vẫn sẽ giữ kết nối sống
  • with tuyên bố không tạo ra một phạm vi mới, do đó tất cả các biến được tạo ra bên trong bộ với sẽ được truy cập bên ngoài nó
  • Cuối cùng, bạn nên đóng kết nối bằng tay
+0

Nếu bạn mở nó, nó vẫn mở cho đến khi nó nằm ngoài phạm vi và rác được thu thập. Tại thời điểm đó nó _might be_ đóng một cách an toàn (và tôi tin rằng 'sqlite3' làm điều đó). Nhưng tốt hơn để được an toàn hơn xin lỗi. Đóng các kết nối của bạn khi bạn không còn sử dụng chúng. – Avaris

+0

Rất vui khi thấy người dùng SO có 6 đại diện quay lại và phản hồi các câu trả lời mà họ cảm thấy không trả lời câu hỏi. Một +1 lớn ở đó. – Droogans

Trả lời

25

Trong câu trả lời cho câu hỏi cụ thể về những gì sẽ xảy ra nếu bạn không đóng một cơ sở dữ liệu SQLite, câu trả lời khá đơn giản và áp dụng cho việc sử dụng SQLite trong bất kỳ chương trình lan nào guage. Khi kết nối được đóng một cách rõ ràng bằng mã hoặc ngầm bằng cách thoát khỏi chương trình thì bất kỳ giao dịch chưa thanh toán nào được quay trở lại. (Việc quay lại thực sự được thực hiện bởi chương trình tiếp theo để mở cơ sở dữ liệu.) Nếu không có giao dịch chưa thanh toán nào mở thì không có gì xảy ra.

Điều này có nghĩa là bạn không cần phải lo lắng quá nhiều về việc luôn đóng cơ sở dữ liệu trước khi thoát khỏi quy trình và bạn nên chú ý đến các giao dịch để đảm bảo bắt đầu và cam kết tại các điểm thích hợp.

+2

Một quy trình chạy dài, chẳng hạn như ứng dụng web, không có ẩn khi thoát, vì không có lối ra. –

1

Phiên bản của bạn để lại phạm vi kết nối sau khi sử dụng kết nối.

VÍ DỤ:

phiên bản của bạn

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 

phiên bản mới

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) 
+13

['with' không tạo ra phạm vi mới.] (Http://stackoverflow.com/questions/6432355/variable-defined-with-with-statement-available-outside-of-with-block)' conn' sẽ là có sẵn sau 'with' trong cả hai trường hợp. – Avaris

6

Bạn có một mối quan tâm cơ bản có giá trị ở đây, tuy nhiên nó cũng quan trọng để hiểu làm thế nào sqlite hoạt động quá:

1. connection open 
    2. transaction started 
     3. statement executes 
    4. transaction done 
5. connection closed 

về dữ liệu đúng đắn, bạn chỉ cần phải lo lắng về các giao dịch và xử lý không mở. sqlite chỉ giữ một khóa trên một cơ sở dữ liệu bên trong một giao dịch (*) hoặc thực thi câu lệnh.

tuy nhiên về mặt số quản lý tài nguyên, ví dụ: nếu bạn định loại bỏ tệp sqlite hoặc sử dụng quá nhiều kết nối, bạn có thể chạy hết các bộ mô tả tệp, bạn cũng quan tâm đến các kết nối mở ngoài giao dịch.

có hai cách kết nối bị đóng: bạn gọi .close() một cách rõ ràng sau đó bạn vẫn có tay cầm nhưng không thể sử dụng hoặc bạn để kết nối nằm ngoài phạm vi và bị thu gom rác.

nếu bạn phải đóng một kết nối, đóng nó lại một cách rõ ràng, theo phương châm của Python "rõ ràng là tốt hơn so với tiềm ẩn."

nếu bạn chỉ kiểm tra mã cho các tác dụng phụ, cho phép biến cuối cùng giữ tham chiếu đến kết nối nằm ngoài phạm vi có thể chấp nhận được, nhưng lưu ý rằng ngoại lệ nắm bắt ngăn xếp và do đó tham chiếu trong ngăn xếp đó. nếu bạn vượt qua các ngoại lệ xung quanh, thời gian kết nối có thể được mở rộng tùy ý.

lập trình báo trước, sqlite sử dụng giao dịch "trì hoãn" theo mặc định, đó là giao dịch chỉ bắt đầu khi bạn thực hiện một câu lệnh. Trong ví dụ trên, giao dịch chạy 3-4, chứ không phải là từ 2 đến 4.

1

Đối với quản lý một kết nối đến một cơ sở dữ liệu Tôi thường làm điều này,

# 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 

làm như vậy, tôi chắc chắn rằng kết nối được đóng một cách rõ ràng.

+2

không đóng kết nối trong trường hợp ngoại lệ bị ném –

2

Bạn có thể sử dụng một khối with như thế này:

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() 
  • kết nối
  • bắt đầu một giao dịch
  • tạo ra một con trỏ db
  • preforms hoạt động và trả về kết quả
  • đóng cửa con trỏ
  • cam kết/Cuộn lại giao dịch
  • đóng kết nối

tất cả an toàn trong cả hai trường hợp hạnh phúc và đặc biệt

3

Đây là mã mà tôi sử dụng. ConnectionCursor sẽ tự động đóng lại nhờ contextlib.closing(). Connection sẽ tự động cam kết nhờ trình quản lý ngữ cảnh.

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) 
Các vấn đề liên quan