Để trả lời trực tiếp câu hỏi của bạn:Tôi không thể thấy bất kỳ tác hại nào khi đóng ở cuối with
khối. Tôi không thể nói tại sao nó không được thực hiện trong trường hợp này. Tuy nhiên, vì có rất ít hoạt động cho câu hỏi này, tôi đã tìm kiếm qua lịch sử mã và sẽ đưa ra một vài suy nghĩ ( phỏng đoán ) về lý do tại sao close()
có thể không được gọi:
-
Có một cơ hội nhỏ là quay vòng qua các cuộc gọi đến
nextset()
có thể đưa ra một ngoại lệ - có thể điều này đã được quan sát thấy và được coi là không mong muốn. Đây có thể là lý do tại sao phiên bản mới hơn củacursors.py
chứa cấu trúc này trongclose()
:def close(self): """Close the cursor. No further queries will be possible.""" if not self.connection: return self._flush() try: while self.nextset(): pass except: pass self.connection = None
-
Có khả năng (hơi xa) rằng có thể mất một thời gian để xem qua tất cả các kết quả còn lại mà không làm gì cả. Do đó,
close()
có thể không được gọi để tránh thực hiện một số lần lặp không cần thiết. Tôi cho rằng bạn có nghĩ rằng việc lưu những chu kỳ đồng hồ đó đáng giá hay không là chủ quan, nhưng bạn có thể tranh luận dọc theo dòng "nếu nó không cần thiết, đừng làm điều đó". -
Duyệt qua các cam kết của sourceforge, chức năng đã được thêm vào thân cây bởi cam kết này vào năm 2007 và có vẻ như phần này của
connections.py
đã không thay đổi kể từ đó. Đó là hợp nhất dựa trên cam kết này , có thông báoVà mã bạn trích dẫn chưa bao giờ thay đổi kể từ đó.
Điều này thúc đẩy suy nghĩ cuối cùng của tôi - nó có thể chỉ là một nỗ lực / nguyên mẫu đầu tiên chỉ hoạt động và do đó không bao giờ bị thay đổi.
Phiên bản hiện đại hơn
Bạn liên kết đến nguồn cho phiên bản cũ của trình kết nối. Tôi lưu ý rằng có một bản fork hoạt động hơn của cùng một thư viện tại đây , mà tôi liên kết đến trong nhận xét của tôi về "phiên bản mới hơn" ở điểm 1.
Lưu ý rằng phiên bản mới hơn của mô-đun này đã triển khai __enter__()
và __exit__()
trong cursor
chính nó: xem tại đây
. __exit__()
đây hiện gọi self.close()
và có lẽ điều này cung cấp một cách chuẩn hơn để sử dụng cú pháp with, ví dụ:
with conn.cursor() as c:
#Do your thing with the cursor
Ghi chú cuối
N.B. Tôi đoán tôi nên thêm vào, theo như tôi hiểu về thu gom rác (cũng không phải là chuyên gia) khi không có tham chiếu nào đến conn
, nó sẽ được phân bổ. Tại thời điểm này, sẽ không có tham chiếu nào đến đối tượng con trỏ và nó cũng sẽ được phân bổ.
Tuy nhiên đang gọi cursor.close()
không có nghĩa là nó sẽ được thu gom rác. Nó chỉ đơn giản là ghi qua các kết quả và đặt kết nối thành None
. Điều này có nghĩa là nó không thể được sử dụng lại, nhưng nó sẽ không được thu gom rác ngay lập tức. Bạn có thể thuyết phục bản thân về điều đó bằng cách gọi thủ công cursor.close()
sau with
khối và sau đó, giả sử, in một số thuộc tính của cursor
N.B. 2 Tôi nghĩ rằng đây là cách sử dụng with
hơi bất thường cú pháp như conn
đối tượng vẫn tồn tại bởi vì nó đã ở trong phạm vi bên ngoài - không giống như, chẳng hạn, with open('filename') as f:
nơi không có đối tượng nào xung quanh với các tham chiếu sau khi kết thúc with
khối.