Близко () необходимый при использовании итератора на объекте файла Python [дубликат]

Современные компиляторы JVM/JIC удалили хит производительности большинства традиционно "медленных" операций, включая instanceof, обработку исключений, отражение, и т.д.

, Как Donald Knuth записал, "Мы должны забыть о маленькой эффективности, сказать приблизительно 97% времени: преждевременная оптимизация является корнем всего зла". Производительность instanceof, вероятно, не будет проблемой, не тратьте впустую свое время, придумывающее экзотические обходные решения, пока Вы не уверены, что это - проблема.

42
задан Dave M. 2 December 2009 в 12:08
поделиться

8 ответов

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

Если вы используете Python 2.5 и выше, close () может вызываться автоматически с помощью оператора with :

from __future__ import with_statement # Only needed in Python 2.5
with open("hello.txt") as f:
    for line in f:
        print line

Это имеет тот же эффект, что и код, который у вас есть:

f = open("hello.txt")
try:
    for line in f:
        print line
finally:
    f.close()

with - это прямая языковая поддержка идиомы Resource Acquisition Is Initialization , обычно используемой в C ++. Это позволяет безопасно использовать и очищать все виды ресурсов, например, его можно использовать, чтобы всегда гарантировать, что соединения с базой данных закрыты или блокировки всегда снимаются, как показано ниже.

mylock = threading.Lock()
with mylock:
    pass # do some thread safe stuff
66
ответ дан 26 November 2019 в 23:24
поделиться

Фактически, файл будет закрыт, когда он будет сборщиком мусора . См. этот вопрос , чтобы узнать, как это работает.

По-прежнему рекомендуется использовать блок try / finally или с оператором . Если при использовании одного из методов файлового объекта возникает исключение, ссылка будет храниться в трассировке (которая хранится как глобальная переменная) до тех пор, пока вы ее не очистите или не произойдет другое исключение.

Таким образом, полагаться на сборку мусора, чтобы закрыть ваш файл за вас.

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

ссылка будет храниться в трассировке (которая хранится как глобальная переменная) до тех пор, пока вы ее не очистите или не произойдет другое исключение.

Таким образом, полагаться на сборку мусора, чтобы закрыть ваш файл за вас.

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

ссылка будет храниться в трассировке (которая хранится как глобальная переменная) до тех пор, пока вы ее не очистите или не возникнет другое исключение.

Таким образом, полагаться на сборку мусора, чтобы закрыть файл за вас.

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

19
ответ дан 26 November 2019 в 23:24
поделиться

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

Конечно, есть случаи, когда это не имеет значения. Если файловый объект выходит за пределы области видимости или удаляется, основной файл будет закрыт. (Время закрытия зависит от конкретной реализации Python, которую вы используете.) Как правило, этого будет достаточно - , если вы точно знаете, когда файловая переменная выйдет за пределы области видимости, и , если вы знаете, что вам все равно, закроется ли файл детерминированно.

12
ответ дан 26 November 2019 в 23:24
поделиться

Это вроде намекает повсюду, но чтобы сделать его максимально ясным, да , вам нужно закрыть этот файл. В Python 2.5 (с использованием future ) и в Python 2.6 вам больше не нужна многословная версия:

from __future__ import with_statement
with open("hello.txt") as f:
    for line in f:
        print line
6
ответ дан 26 November 2019 в 23:24
поделиться

При выходе интерпретатор Python (или ядро ​​в случае сбоя) закроет файл, но по-прежнему рекомендуется закрывать их, когда они вам не нужны. Для 1, 2 или 10 файлов это может не быть проблемой, но для большего количества это может вывести из строя всю систему.

Самое главное, это знак того, что человек, написавший код, действительно заботится о своей работе.

5
ответ дан 26 November 2019 в 23:24
поделиться

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

2
ответ дан 26 November 2019 в 23:24
поделиться

Нет, я не считаю, что более длинная идиома необходима, и вот почему:

Я нашел /usr/lib/python2.6/ для шаблона 'для \ s +. * \ S + in \ s + open \ (' и нашел много примеров

for line in open('hello.txt'):
    print line

и пока ноль экземпляров

f = open("hello.txt")
try:
    for line in f:
        print line
finally:
    f.close()

. См. ниже список файлов в стандартной библиотеке, которые используют for ... в открытой идиоме .

Это естественно приводит к вопросу: если разработчики Python принимают более короткую идиому в стандартные библиотеки, как мы можем что-то улучшить, используя что-то отличается в нашем собственном коде, если наш код зависит от стандартных библиотек?

Думаю, ответ таков: более длинная идиома ничего не улучшает.

Я также запустил

#!/usr/bin/env python
try:
    for i,line in enumerate(open('a')):
        print line
        raw_input()
        if i==5:
            break
except Exception:
    pass

raw_input()

и проверил / proc / PID / fd , когда дескриптор файла был закрыт. Похоже, что когда вы выходите из цикла for, файл закрывается для вас.

На основании этих экспериментов я не верю, что длинный попробуйте ... наконец ... закрыть идиома необходима.

Вот результат grep:

/usr/lib/python2.6/dist-packages/NvidiaDetector/nvidiadetector.py:89:tempList = [ x.strip() for x in open(obsolete).readlines() ]
/usr/lib/python2.6/dist-packages/rpy_io.py:49:for line in open(file).readlines():
/usr/lib/python2.6/dist-packages/setuptools/command/easy_install.py:1376:for line in open(self.filename,'rt'):
/usr/lib/python2.6/dist-packages/GDebi/DscSrcPackage.py:47:for line in open(file):
/usr/lib/python2.6/dist-packages/aptsources/distinfo.py:220:[x.strip() for x in open(value)])
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeCache.py:989:for line in open("/proc/mounts"):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeAufs.py:100:for line in open("/proc/mounts"):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeAufs.py:205:for line in open("/proc/mounts"):
/usr/lib/python2.6/dist-packages/DistUpgrade/distinfo.py:220:[x.strip() for x in open(value)])
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeViewKDE.py:826:for c in open(sys.argv[2]).read():
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeConfigParser.py:45:items = [x.strip() for x in open(p)]
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeQuirks.py:684:for line in open(cpuinfo):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeQuirks.py:692:for line in open("/proc/mounts"):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeQuirks.py:726:for line in open("/etc/fstab"):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeQuirks.py:762:for line in open(fstab):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeQuirks.py:801:for line in open("/etc/fstab"):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeQuirks.py:874:for line in open(XORG):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeQuirks.py:939:for line in open(os.path.join(modaliasesdir,filename)):
/usr/lib/python2.6/dist-packages/DistUpgrade/DistUpgradeController.py:1307:for line in open(template):
/usr/lib/python2.6/dist-packages/DistUpgrade/xorg_fix_proprietary.py:23:for raw in open(xorg_source):
/usr/lib/python2.6/dist-packages/DistUpgrade/xorg_fix_proprietary.py:58:for line in open(xorg):
/usr/lib/python2.6/dist-packages/DistUpgrade/xorg_fix_proprietary.py:82:for line in open(xorg):
/usr/lib/python2.6/dist-packages/jockey/oslib.py:377:for line in open(self.apt_jockey_source):
/usr/lib/python2.6/dist-packages/jockey/oslib.py:393:for line in open(f):
/usr/lib/python2.6/dist-packages/jockey/backend.py:651:for line in open(path):
/usr/lib/python2.6/dist-packages/jockey/detection.py:277:for line in open(alias_file):
/usr/lib/python2.6/dist-packages/jockey/detection.py:597:for l in open(os.path.join(path, 'uevent')):
/usr/lib/python2.6/dist-packages/apt/cdrom.py:83:for line in open(fname):
/usr/lib/python2.6/dist-packages/problem_report.py:1119:for line in open('/proc/mounts'):
/usr/lib/python2.6/dist-packages/apport/packaging_impl.py:128:for line in open(f):
/usr/lib/python2.6/dist-packages/apport/packaging_impl.py:190:for line in open(sumfile):
/usr/lib/python2.6/dist-packages/apport/packaging_impl.py:641:for l in open('/etc/apt/sources.list'):
/usr/lib/python2.6/dist-packages/apport/hookutils.py:190:for line in open('/proc/asound/cards'):
/usr/lib/python2.6/dist-packages/apport/hookutils.py:290:for line in open('/var/log/syslog'):
/usr/lib/python2.6/dist-packages/apport/hookutils.py:493:mods = [l.split()[0] for l in open(module_list)]
/usr/lib/python2.6/dist-packages/softwareproperties/SoftwareProperties.py:597:for line in open(f):
/usr/lib/python2.6/dist-packages/softwareproperties/gtk/SoftwarePropertiesGtk.py:883:for x in open(tmp.name):
/usr/lib/python2.6/dist-packages/lsb_release.py:253:for line in open('/etc/lsb-release'):
/usr/lib/python2.6/dist-packages/numpy/distutils/system_info.py:815:for d in open(ld_so_conf,'r').readlines():
/usr/lib/python2.6/dist-packages/LanguageSelector/LocaleInfo.py:72:for line in open(languagelist_file):
/usr/lib/python2.6/dist-packages/LanguageSelector/LocaleInfo.py:187:for line in open(environment).readlines():
/usr/lib/python2.6/dist-packages/LanguageSelector/LocaleInfo.py:193:for line in open(environment).readlines():
/usr/lib/python2.6/dist-packages/LanguageSelector/LanguageSelector.py:125:for line in open(fname):
/usr/lib/python2.6/dist-packages/LanguageSelector/LanguageSelector.py:140:for line in open(fname):
/usr/lib/python2.6/dist-packages/LanguageSelector/LanguageSelector.py:171:for line in open(fname):
/usr/lib/python2.6/dist-packages/LanguageSelector/LanguageSelector.py:210:for line in open(fname):
/usr/lib/python2.6/dist-packages/LanguageSelector/macros.py:16:for l in open(file):
/usr/lib/python2.6/dist-packages/LanguageSelector/macros.py:37:for l in open(self.LANGCODE_TO_LOCALE):
/usr/lib/python2.6/dist-packages/LanguageSelector/LangCache.py:94:for l in open(self.BLACKLIST):
/usr/lib/python2.6/dist-packages/LanguageSelector/LangCache.py:99:for l in open(self.LANGCODE_TO_LOCALE):
/usr/lib/python2.6/dist-packages/LanguageSelector/LangCache.py:111:for l in open(self.PACKAGE_DEPENDS):
/usr/lib/python2.6/dist-packages/LanguageSelector/ImSwitch.py:78:for l in open(self.blacklist_file):
3
ответ дан 26 November 2019 в 23:24
поделиться

Да, потому что в противном случае может произойти утечка ресурсов.

Из документации Python :

Когда вы закончите работу с файлом, позвоните f .close () , чтобы закрыть его и освободить любые системные ресурсы, занятые открытым файлом.

Это произойдет с вами, когда программа завершится, но в противном случае Python сохраняет ресурсы, которые ему больше не нужны. точка.

3
ответ дан 26 November 2019 в 23:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: