Подтвердить что ты не робот

Автоматически закрывается ли объект файла, когда его количество ссылок подсчитывается в нуле?

У меня создалось впечатление, что файловые объекты сразу же закрываются, когда их число ссылок достигает 0, поэтому строка:

foo = open('foo').read()

предоставит вам содержимое файла и сразу закроет файл. Однако после прочтения ответа на Is close() необходимо при использовании итератора в объекте Python. У меня создается впечатление, что этого не происходит, и что вызов .close() для файлового объекта всегда необходимо.

Выполняет ли линия выше то, что я думаю, что она делает, и даже если это так, это питоновская вещь?

4b9b3361

Ответ 1

Ответ указан в указанной вами ссылке.

Сборщик мусора закрывает файл, когда он уничтожает файл-объект, но:

  • у вас действительно нет контроля над тем, когда это произойдет.

    В то время как CPython использует подсчет ссылок для детерминированного выделения ресурсов (так что вы можете предсказать, когда объект будет уничтожен) другим версиям не нужно. Например, как Jython, так и IronPython используют сборщик мусора JVM и .NET, который освобождать (и завершать) объекты только тогда, когда необходимо восстановить память и может не сделать этого для какого-либо объекта до конца программы. И даже для CPython GC алгоритм может измениться в будущем как подсчет ссылок не очень эффективен.

  • если исключение вызывается при закрытии файла при уничтожении объекта файла, вы не можете ничего с этим поделать, потому что не знаете.

Ответ 2

Если вы хотите быть уверенным, я бы написал код следующим образом:

from __future__ import with_statement

with open('foo') as f:
    foo = f.read()

Таким образом, ваш файл закрывается, как ожидалось, даже с исключениями.


Много позже: вот какой-то код с import dis, чтобы показать, как компилятор рассматривает их по-разному.

>>> def foo(filename):
...     with open(filename) as f:
...         return f.read()
... 
>>> def bar(filename):
...     return open(filename).read()
... 
>>> from dis import dis
>>> 
>>> dis(foo)
  2           0 LOAD_GLOBAL              0 (open)
              3 LOAD_FAST                0 (filename)
              6 CALL_FUNCTION            1
              9 DUP_TOP             
             10 LOAD_ATTR                1 (__exit__)
             13 ROT_TWO             
             14 LOAD_ATTR                2 (__enter__)
             17 CALL_FUNCTION            0
             20 STORE_FAST               1 (_[1])
             23 SETUP_FINALLY           23 (to 49)
             26 LOAD_FAST                1 (_[1])
             29 DELETE_FAST              1 (_[1])
             32 STORE_FAST               2 (f)

  3          35 LOAD_FAST                2 (f)
             38 LOAD_ATTR                3 (read)
             41 CALL_FUNCTION            0
             44 RETURN_VALUE        
             45 POP_BLOCK           
             46 LOAD_CONST               0 (None)
        >>   49 WITH_CLEANUP        
             50 END_FINALLY         
             51 LOAD_CONST               0 (None)
             54 RETURN_VALUE        
>>> dis(bar)
  2           0 LOAD_GLOBAL              0 (open)
              3 LOAD_FAST                0 (filename)
              6 CALL_FUNCTION            1
              9 LOAD_ATTR                1 (read)
             12 CALL_FUNCTION            0
             15 RETURN_VALUE 

Ответ 3

Для реализации python cpython: да, он будет закрыт, когда счетчик ссылок будет равен нулю.

Для python как абстрактного языка (например, включая Jython, IronPython и т.д.): нет, он не гарантированно закрыт. В частности, реализация Python может не использовать подсчет ссылок, а использовать другую форму GC.

Литература:

Ответ 4

Нет, Python оптимизирует удаление неиспользуемых объектов, поэтому он никогда не сможет закрыть ваш файл (ОК в конце вашего script на выходе он будет очищать). @hughdbrown отметили приятное решение.