закрытие файлов, правильно открываемых с помощью urllib2.urlopen ()
У меня есть код в сценарии python
try: # send the query request sf = urllib2.urlopen(search_query) search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read()) sf.close() except Exception, err: print("Couldn't get programme information.") print(str(err)) return
Я обеспокоен тем, что если я столкнулся с ошибкой в sf.read()
, то sf.clsoe()
не вызывается. Я попытался поместить sf.close()
в блок finally
, но если в urlopen()
есть исключение, нет файла для закрытия, и я получаю исключение в блоке finally
!
- кодировка python urllib2 utf-8
- cURL: https через прокси-сервер
- Python Urllib2 Cookiejar с селеном
- Загрузка веб-страницы и всех ее файлов ресурсов в Python
- Ошибка - ошибка urlopen _ssl.c: 504: EOF произошел с нарушением протокола, нужна помощь
Итак, я попробовал
try: with urllib2.urlopen(search_query) as sf: search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read()) except Exception, err: print("Couldn't get programme information.") print(str(err)) return
но это привело к недопустимой синтаксической ошибке в строке with...
Как я могу лучше справиться с этим, я чувствую себя глупо!
Как отмечают комментаторы, я использую Pys60, который является python 2.5.4
- Проблемы с загрузкой файлов Python urllib2
- Python / Django скачать изображение с URL, изменить и сохранить в ImageField
- Python urllib2 Основная проблема с Auth
- Хороший способ получить кодировку / кодировку ответа HTTP в Python
- Как отправить не-ASCII-символы с помощью httplib, когда content-type - "application / xml"
8 Solutions collect form web for “закрытие файлов, правильно открываемых с помощью urllib2.urlopen ()”
Почему бы просто не попробовать закрыть sf
и пропустить, если он не существует?
import urllib2 try: search_query = 'http://blah' sf = urllib2.urlopen(search_query) search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read()) except urllib2.URLError, err: print(err.reason) finally: try: sf.close() except NameError: pass
Я бы использовал contextlib.closing (в сочетании с __future__ import with_statement для старых версий Python):
from contextlib import closing with closing(urllib2.urlopen('http://blah')) as sf: search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read())
Или, если вы хотите избежать утверждения with:
try: sf = None sf = urllib2.urlopen('http://blah') search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read()) finally: if sf: sf.close()
Не совсем так элегантно.
finally: if sf: sf.close()
Учитывая, что вы пытаетесь использовать «с», вы должны быть на Python 2.5, а затем это тоже относится: http://docs.python.org/tutorial/errors.html#defining-clean-up -actions
Похоже, проблема идет глубже, чем я думал – этот поток форума указывает, что urllib2 не реализуется до тех пор, пока не будет python 2.6, и, возможно, не до 3.1
Вы можете создать свой собственный универсальный открыватель URL:
from contextlib import contextmanager @contextmanager def urlopener(inURL): """Open a URL and yield the fileHandle then close the connection when leaving the 'with' clause.""" fileHandle = urllib2.urlopen(inURL) try: yield fileHandle finally: fileHandle.close()
Затем вы можете использовать свой синтаксис из исходного вопроса:
with urlopener(theURL) as sf: search_soup = BeautifulSoup.BeautifulSoup(sf.read())
Это решение дает вам четкое разделение проблем. Вы получаете чистый общий синтаксис urlopener, который обрабатывает сложности правильного закрытия ресурса, независимо от ошибок, которые возникают под вашим предложением.
Почему бы просто не использовать несколько блоков try / except?
try: # send the query request sf = urllib2.urlopen(search_query) except urllib2.URLError as url_error: sys.stderr.write("Error requesting url: %s\n" % (search_query,)) raise try: search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read()) except Exception, err: # Maybe catch more specific Exceptions here sys.stderr.write("Couldn't get programme information from url: %s\n" % (search_query,)) raise # or return as in your original code finally: sf.close()
Если urlopen () имеет исключение, поймайте его и вызовите функцию close () исключения следующим образом:
try: req = urllib2.urlopen(url) req.close() print 'request {0} ok'.format(url) except urllib2.HTTPError, e: e.close() print 'request {0} failed, http code: {1}'.format(url, e.code) except urllib2.URLError, e: e.close() print 'request {0} error, error reason: {1}'.format(url, e.reason)
исключение также является полным объектом ответа, вы можете увидеть это сообщение об ошибке : http://bugs.jython.org/issue1544
- В Django, как мне получить escaped html в HttpResponse?
- Простой способ создания 2D-массива со случайными числами (Python)