следует ли мне вызывать close() после urllib.urlopen()?
Вопрос
Я новичок в Python и читаю чужой код:
должен urllib.urlopen()
сопровождаться urllib.close()
?В противном случае произойдет утечка соединений, верно?
Решение
А 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
контекстный менеджер обеспечит правильное закрытие даже при наличии исключений.
Другие советы
Как говорит @Peter, открытые URL-адреса, выходящие за рамки области действия, получат право на сбор мусора.
Однако также обратите внимание, что urllib.py
определяет:
def __del__(self):
self.close()
Это значит, что когда счетчик ссылок для этого экземпляра достигает нуля, его __del__
будет вызван метод, и, следовательно, его close
метод также будет вызван.Самый «нормальный» способ достижения нуля счетчиком ссылок — это просто позволить экземпляру выйти за пределы области видимости, но ничто строго не мешает вам явно del x
рано (однако он не вызывает напрямую __del__
но просто уменьшает счетчик ссылок на единицу).
Явное закрытие ресурсов, безусловно, хороший стиль, особенно если ваше приложение рискует использовать слишком много этих ресурсов, но Python воля автоматически очищается за вас, если вы не делаете ничего странного, например, сохраняете (циклические?) ссылки на экземпляры, которые вам больше не нужны.
Строго говоря, это правда.Но на практике однажды (если) urllib
выходит за рамки, соединение будет закрыто автоматическим сборщиком мусора.
Вы в основном делать необходимо явно закрыть соединение при использовании ЖелезоПитон.Автоматическое закрытие при выходе за пределы области действия зависит от сборки мусора.Я столкнулся с ситуацией, когда сборка мусора не выполнялась так долго, что в Windows закончились сокеты.Я опрашивал веб-сервер с высокой частотой (т.настолько высоко, насколько позволяет IronPython и соединение, ~7 Гц).Я мог видеть «установленные связи» (т.е.используемые сокеты) растут и растут в PerfMon.Решением было позвонить gc.collect()
после каждого звонка urlopen
.