я должен вызвать close () после urllib.urlopen ()? - PullRequest
68 голосов
/ 06 октября 2009

Я новичок в Python и читаю чужой код:

должно urllib.urlopen() сопровождаться urllib.close()? В противном случае произошла бы утечка соединений, правильно?

Ответы [ 4 ]

98 голосов
/ 06 октября 2009

Метод close должен быть вызван для результата из urllib.urlopen, , а не для самого модуля urllib, как вы думаете (как вы упоминаете urllib.close - чего не существует).

Лучший подход: вместо x = urllib.urlopen(u) и т. Д. Используйте:

import contextlib

with contextlib.closing(urllib.urlopen(u)) as x:
   ...use x at will here...

Оператор with и менеджер контекста closing обеспечат правильное закрытие даже при наличии исключений.

12 голосов
/ 06 октября 2009

Как говорит @Peter, открытые URL за пределами области действия будут иметь право на сборку мусора.

Однако также обратите внимание, что urllib.py определяет:

 def __del__(self):
        self.close()

Это означает, что когда счетчик ссылок для этого экземпляра достигнет нуля , будет вызван его метод __del__, и, следовательно, будет вызван его метод close. Самый «нормальный» способ для подсчета ссылок достигнуть нуля - просто позволить экземпляру выйти из области видимости, но ничто не помешает вам строго от del x на ранней стадии (однако это не вызывает непосредственно __del__, а просто уменьшает счетчик ссылок на единицу).

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

4 голосов
/ 06 октября 2009

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

0 голосов
/ 12 марта 2019

Вы в основном делаете необходимо явно закрыть ваше соединение при использовании IronPython . Автоматическое закрытие при выходе из области зависит от сборки мусора. Я столкнулся с ситуацией, когда сборка мусора не выполнялась так долго, что в Windows не хватало сокетов. Я опрашивал веб-сервер на высокой частоте (т. Е. Так высоко, как IronPython, и соединение позволяло, ~ 7 Гц). Я мог видеть, как «установленные соединения» (т.е. используемые сокеты) поднимаются и увеличиваются в PerfMon. Решением было звонить gc.collect() после каждого звонка urlopen.

...