Hướng dẫn do you have to close with open python? - bạn có phải đóng bằng trăn mở không?

Ngày 18 tháng 1 năm 2015. Bởi reuven. By Reuven

Một trong những điều đầu tiên mà các lập trình viên Python học được là bạn có thể dễ dàng đọc qua nội dung của một tệp mở bằng cách lặp lại nó:

f = open('/etc/passwd')
for line in f:
    print(line)

Lưu ý rằng mã trên là có thể bởi vì đối tượng tệp của chúng tôi là F F F F F F F F F F F F F F F F F F F F F F F F F F F F. Nói cách khác, F biết cách cư xử bên trong một vòng lặp - hoặc bất kỳ bối cảnh lặp lại nào khác, chẳng hạn như sự hiểu biết danh sách.

Hầu hết các sinh viên trong các khóa học Python của tôi đến từ các ngôn ngữ lập trình khác, trong đó họ dự kiến ​​sẽ đóng một tệp khi họ sử dụng nó. Do đó, nó không làm tôi ngạc nhiên khi, ngay sau khi tôi giới thiệu chúng với các tệp trong Python, họ hỏi làm thế nào chúng tôi dự kiến ​​sẽ đóng chúng.

Câu trả lời đơn giản nhất là chúng ta có thể đóng tệp của mình một cách rõ ràng bằng cách gọi f.Close (). Khi chúng ta đã làm điều đó, đối tượng tiếp tục tồn tại - nhưng chúng ta không còn có thể đọc được từ nó nữa và biểu diễn in của đối tượng cũng sẽ chỉ ra rằng tệp đã bị đóng:

>>> f = open('/etc/passwd')
>>> f

>>> f.read(5)
'##\n# '

f.close()
>>> f


f.read(5)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
 in ()
----> 1 f.read(5)
ValueError: I/O operation on closed file

Nhưng ở đây, điều này: Khi tôi lập trình ở Python, nó khá hiếm khi tôi gọi rõ ràng phương thức đóng của Google trên một tập tin. Hơn nữa, tỷ lệ cược là tốt mà bạn có thể không muốn hoặc cần phải làm như vậy.

Cách mở các tệp mở được ưa thích, tốt nhất là với câu lệnh của With với câu lệnh, như sau:

with open('/etc/passwd') as f:
    for line in f:
        print(line)

Tuyên bố của người Viking với những gì Python gọi là người quản lý bối cảnh của người Hồi giáo trên f. Đó là, nó gán f là thể hiện tệp mới, trỏ đến nội dung của /etc /passwd. Trong khối mã được mở bởi nhóm With With, tệp của chúng tôi được mở và có thể được đọc từ tự do.

Tuy nhiên, một khi Python thoát ra khỏi khối với khối với khối, tệp sẽ tự động đóng. Cố gắng đọc từ F sau khi chúng tôi đã thoát khỏi khối với khối với khối sẽ dẫn đến ngoại lệ giá trị tương tự mà chúng tôi đã thấy ở trên. Python làm điều đó cho bạn, theo một cách hơi không pythonic, một cách kỳ diệu, âm thầm và đằng sau hậu trường.

Nhưng điều gì sẽ xảy ra nếu bạn không đóng lại rõ ràng tập tin thì sao? Điều gì sẽ xảy ra nếu bạn có một chút lười biếng, và không sử dụng một khối với khối hay không gọi f.close ()? & nbsp; khi nào tệp đóng? & nbsp; khi nào & nbsp; tập tin có nên được đóng không?

Tôi hỏi điều này, bởi vì tôi có & nbsp; đã dạy Python cho nhiều người trong nhiều năm qua, và tin rằng cố gắng dạy cho các nhà quản lý và/hoặc/hoặc các nhà quản lý bối cảnh, đồng thời cố gắng dạy nhiều chủ đề khác, nhiều hơn học sinh có thể hấp thụ. Mặc dù tôi chạm vào trên các nhóm với các lớp giới thiệu của mình, tôi thường nói với họ rằng tại thời điểm này trong sự nghiệp của họ, thì thật tốt khi để Python đóng các tệp, khi tính toán tham chiếu đến đối tượng tệp giảm xuống 0 hoặc khi Python thoát ra.

Trong & nbsp; khóa học e-mail miễn phí & nbsp; của tôi về việc làm việc với các tệp python, tôi đã có một cái nhìn tương tự về mọi thứ và không sử dụng nó trong tất cả các giải pháp được đề xuất của tôi. & Nbsp; một số người đã thách thức tôi, nói rằng không sử dụng Càng với người Viking đang cho mọi người thấy một thực tiễn tồi tệ và có nguy cơ có dữ liệu không được lưu vào đĩa.

Tôi đã có đủ e-mail về chủ đề để tự hỏi: Khi nào Python đóng các tập tin, nếu chúng tôi không thể tự làm như vậy hoặc sử dụng một khối với khối với khối? Đó là, nếu tôi để tệp đóng tự động, thì tôi có thể mong đợi điều gì?

Giả định của tôi luôn luôn là Python đóng các tệp khi số lượng tham chiếu của đối tượng giảm xuống 0, và do đó là rác được thu thập. Điều này rất khó để chứng minh hoặc kiểm tra khi chúng tôi đã mở một tệp để đọc, nhưng nó rất dễ kiểm tra khi chúng tôi mở một tệp để viết. Điều đó bởi vì khi bạn viết vào một tệp, các nội dung đã ngay lập tức chuyển sang đĩa (trừ khi bạn vượt qua Sai False, là đối số thứ ba, tùy chọn cho Mở Open), nhưng chỉ bị xóa khi tệp được đóng.

Do đó, tôi đã quyết định tiến hành một số thí nghiệm, để hiểu rõ hơn những gì tôi có thể (và không thể) mong đợi Python sẽ tự động làm cho tôi. Thử nghiệm của tôi bao gồm mở một tệp, viết một số dữ liệu cho nó, xóa tham chiếu và sau đó thoát khỏi Python. Tôi tò mò muốn biết khi nào dữ liệu sẽ được viết, nếu có bao giờ.

Thử nghiệm của tôi trông như thế này:

f = open('/tmp/output', 'w')
f.write('abc\n')
f.write('def\n')
# check contents of /tmp/output (1)
del(f)
# check contents of /tmp/output (2)
# exit from Python
# check contents of /tmp/output (3)

Trong thử nghiệm đầu tiên của tôi, được thực hiện với Python 2.7.9 trên máy Mac của tôi, tôi có thể báo cáo rằng ở giai đoạn (1) tệp tồn tại nhưng trống và ở các giai đoạn (2) và (3), tệp chứa tất cả các nội dung của nó. Do đó, có vẻ như trong Cpython 2.7, trực giác ban đầu của tôi là chính xác: khi một đối tượng tệp được thu thập rác, __del__ (hoặc tương đương của nó) xả và đóng tệp. Và thực sự, việc gọi LS LSOF trên quy trình Ipython của tôi cho thấy rằng tệp đã được đóng sau khi loại bỏ tham chiếu.

Còn Python 3 thì sao? & nbsp; Tôi đã chạy thử nghiệm trên theo Python 3.4.2 trên máy Mac của mình và có kết quả giống hệt nhau. Loại bỏ tham chiếu cuối cùng (tốt, chỉ) đến đối tượng tệp dẫn đến tệp được xóa và đóng.

Điều này là tốt cho 2,7 và 3,4. & nbsp; Nhưng còn các triển khai thay thế, chẳng hạn như Pypy và Jython? & nbsp; có lẽ họ làm mọi thứ khác nhau.

Do đó, tôi đã thử cùng một thử nghiệm & nbsp; theo Pypy 2.7.8. Và lần này, tôi đã nhận được kết quả khác nhau! Tôi phải cho rằng điều này có liên quan đến sự khác biệt trong bộ thu gom rác, hoặc một cái gì đó khác hoạt động khác nhau trong pypy so với CPython. Nhưng nếu bạn đang chạy các chương trình trong Pypy, thì bạn chắc chắn không nên mong đợi các tệp sẽ bị xóa và đóng, chỉ vì tham chiếu cuối cùng chỉ vào chúng đã bị mất phạm vi. LSOF cho thấy tập tin bị kẹt xung quanh cho đến khi quá trình Python thoát ra. Deleting the reference to our file object — that is, stage (2), did not result in the file’s contents being flushed to disk. I have to assume that this has to do with differences in the garbage collector, or something else that works differently in PyPy than in CPython. But if you’re running programs in PyPy, then you should definitely not expect files to be flushed and closed, just because the final reference pointing to them has gone out of scope. lsof showed that the file stuck around until the Python process exited.

Để giải trí, tôi quyết định thử Jython 2.7b3. Và Jython thể hiện hành vi tương tự như Pypy. & nbsp; nghĩa là, thoát khỏi Python luôn đảm bảo rằng dữ liệu được xóa từ bộ đệm và được lưu trữ vào đĩa.

Tôi đã lặp lại những thí nghiệm này, nhưng thay vì viết về ABC \ n, và DEF DEF

Trong trường hợp của Python 2.7, không có gì được viết sau ABC \ n, * 1000. Nhưng khi tôi viết ra def def \ n, * 1000, tệp chứa 4096 byte - có thể chỉ ra kích thước bộ đệm. Gọi del (f) để xóa tham chiếu đến đối tượng tệp dẫn đến việc bị xóa và đóng, với tổng số 8.000 byte. Vì vậy, trong trường hợp của Python 2.7, hành vi về cơ bản là giống nhau bất kể kích thước chuỗi; Sự khác biệt duy nhất là nếu bạn vượt quá kích thước của bộ đệm, thì một số dữ liệu sẽ được ghi vào đĩa trước khi kết thúc cuối cùng + đóng.

Trong trường hợp của Python 3, hành vi này là khác nhau: không có dữ liệu nào được viết sau một trong hai đầu ra 4.000 byte được viết bằng f.write. Nhưng ngay khi tham chiếu được xóa, tệp đã được xóa và đóng. Điều này có thể chỉ ra một kích thước bộ đệm lớn hơn. Tuy nhiên, điều đó có nghĩa là việc loại bỏ tham chiếu cuối cùng đến một tệp khiến tệp bị xóa và đóng.

Trong trường hợp của Pypy và Jython, hành vi với một tệp lớn giống như với một tệp nhỏ: tệp đã bị xóa và đóng khi quá trình Pypy hoặc Jython thoát ra, không phải khi loại bỏ tham chiếu cuối cùng đến đối tượng tệp.

Chỉ để kiểm tra lại, tôi cũng đã thử những thứ này bằng cách sử dụng với với với. Trong tất cả các trường hợp này, thật dễ dàng để dự đoán khi nào tệp sẽ bị xóa và đóng: khi khối thoát ra, và người quản lý bối cảnh đã bắn phương thức thích hợp đằng sau hậu trường.

Nói cách khác: nếu bạn không sử dụng với các trò chơi với các trò chơi, thì dữ liệu của bạn không nhất thiết phải có nguy cơ biến mất - ít nhất, không phải trong các tình huống đơn giản. Tuy nhiên, bạn không thể biết chắc chắn khi nào dữ liệu sẽ được lưu - cho dù đó là khi loại tham chiếu cuối cùng được xóa hoặc khi chương trình thoát ra. Nếu bạn giả định rằng các tệp sẽ được đóng khi các chức năng quay trở lại, bởi vì tham chiếu duy nhất cho tệp nằm trong một biến cục bộ, thì bạn có thể gây bất ngờ. Và nếu bạn có nhiều quy trình hoặc chủ đề ghi vào cùng một tệp, thì bạn sẽ thực sự muốn cẩn thận ở đây.

Có lẽ hành vi này có thể được chỉ định tốt hơn, và do đó hoạt động tương tự hoặc giống hệt nhau trên các nền tảng khác nhau? Có lẽ chúng ta thậm chí có thể thấy sự khởi đầu của một đặc điểm kỹ thuật Python, thay vì chỉ vào Cpython và nói, Yeah Yeah, bất cứ phiên bản nào & nbsp; làm là điều đúng đắn.

Tôi vẫn nghĩ rằng, với các nhà quản lý và các nhà quản lý bối cảnh là tuyệt vời. Và tôi vẫn nghĩ rằng những người mới đến khó khăn để hiểu những gì mà với những người khác làm. Nhưng tôi cũng nghĩ rằng tôi sẽ phải bắt đầu cảnh báo các nhà phát triển mới rằng nếu họ quyết định sử dụng các phiên bản thay thế của Python, thì có tất cả các loại trường hợp cạnh kỳ lạ có thể không hoạt động giống hệt với Cpython và điều đó có thể cắn chúng khó khăn nếu chúng ' RE không cẩn thận.

Thích bài viết này? Tham gia cùng hơn 11.000 nhà phát triển khác nhận bản tin của các nhà phát triển tốt hơn, hàng tuần của tôi. Mỗi thứ Hai, bạn sẽ nhận được một bài viết như thế này về phát triển phần mềm và Python:

Bạn có nên đóng cửa với Python mở không?

Bạn đã học tại sao điều quan trọng là đóng các tệp trong Python. Vì các tệp là tài nguyên hạn chế được quản lý bởi hệ điều hành, việc đảm bảo các tệp được đóng sau khi sử dụng sẽ bảo vệ chống lại các sự cố khó có nghĩa là hết tay cầm hoặc trải nghiệm dữ liệu bị hỏng.making sure files are closed after use will protect against hard-to-debug issues like running out of file handles or experiencing corrupted data.

Điều gì xảy ra nếu bạn không đóng Python?

Python không xóa bộ đệm, nghĩa là, hãy viết dữ liệu vào tệp, cho đến khi chắc chắn bạn đã viết xong và một cách để làm điều này là đóng tệp.Nếu bạn ghi vào một tệp mà không đóng, dữ liệu sẽ không được đưa vào tệp đích.the data won't make it to the target file.

Làm thế nào với công việc mở trong Python?

Làm thế nào để tuyên bố hoạt động trong Python?Câu lệnh With hoạt động với hàm Open () để mở tệp.Không giống như Open () nơi bạn phải đóng tệp bằng phương thức đóng (), câu lệnh với câu lệnh đóng tệp cho bạn mà không cần bạn nói.The with statement works with the open() function to open a file. Unlike open() where you have to close the file with the close() method, the with statement closes the file for you without you telling it to.

Sự khác biệt giữa python mở () và đóng () là gì?

Open () như tên nó ngụ ý được sử dụng để mở tệp dữ liệu trong một chương trình thông qua đối tượng tệp và đóng () được sử dụng để đóng () liên kết của tệp tệp và tệp dữ liệu.Khi tệp dữ liệu được đóng, không có hoạt động nào có thể được thực hiện.. Once data file is closed, no operation can be performed.