7

我在 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()不会调用 then 。我尝试放入sf.close()一个finally块,但如果出现异常,urlopen()则没有要关闭的文件,我在块中遇到异常finally

所以我尝试了

  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...。我怎么能最好地处理这个,我觉得很愚蠢!

正如评论者所指出的,我使用的是 Python 2.5.4 Pys60

4

8 回答 8

18

我会使用 contextlib.closure (结合 from __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()

虽然没有那么优雅。

于 2013-02-13T08:18:28.673 回答
8
finally:
    if sf: sf.close()
于 2010-10-07T12:22:23.733 回答
7

为什么不尝试关闭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
于 2010-10-07T11:32:34.180 回答
1

鉴于您正在尝试使用“with”,您应该使用 Python 2.5,然后这也适用:http ://docs.python.org/tutorial/errors.html#defining-clean-up-actions

于 2010-10-07T10:44:56.923 回答
1

如果 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:
    print 'request {0} error, error reason: {1}'.format(url, e.reason)

异常也是一个完整的响应对象,你可以看到这个问题消息:http ://bugs.jython.org/issue1544

于 2017-05-19T02:43:51.043 回答
0

看起来问题比我想象的要深入 -这个论坛帖子表明 urllib2with直到 python 2.6 之后才实现,可能直到 3.1

于 2010-10-07T11:20:01.907 回答
0

您可以创建自己的通用 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 语法,该语法可以处理正确关闭资源的复杂性,而不管您的 with 子句下发生的错误如何。

于 2013-08-25T15:15:55.177 回答
0

为什么不直接使用多个 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()
于 2015-03-24T13:28:39.443 回答