关闭使用 urllib2.urlopen() 正确打开的文件

发布于 2024-09-26 07:44:52 字数 900 浏览 4 评论 0原文

我担心 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 块中遇到异常!

然后我尝试了

  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

I have following code in a python script

  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

I'm concerned because if I encounter an error on sf.read(), then sf.clsoe() is not called.
I tried putting sf.close() in a finally block, but if there's an exception on urlopen() then there's no file to close and I encounter an exception in the finally block!

So then I tried

  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

but this raised a invalid syntax error on the with... line.
How can I best handle this, I feel stupid!

As commenters have pointed out, I am using Pys60 which is python 2.5.4

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

物价感观 2024-10-03 07:44:52

我会使用 contextlib.looking (与旧 Python 版本的 from __future__ import with_statement 结合使用):

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()

但不太优雅。

I would use contextlib.closing (in combination with from __future__ import with_statement for old Python versions):

from contextlib import closing

with closing(urllib2.urlopen('http://blah')) as sf:
    search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read())

Or, if you want to avoid the with statement:

try:
    sf = None
    sf = urllib2.urlopen('http://blah')
    search_soup = BeautifulSoup.BeautifulStoneSoup(sf.read())
finally:
    if sf:
        sf.close()

Not quite as elegant though.

风启觞 2024-10-03 07:44:52
finally:
    if sf: sf.close()
finally:
    if sf: sf.close()
苏佲洛 2024-10-03 07:44:52

为什么不直接尝试关闭 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

Why not just try closing sf, and passing if it doesn't exist?

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
爱情眠于流年 2024-10-03 07:44:52

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

Given that you are trying to use 'with', you should be on Python 2.5, and then this applies too: http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

情徒 2024-10-03 07:44:52

如果 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

If urlopen() has an exception, catch it and call the exception's close() function, like this:

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)

the exception is also a full response object, you can see this issue message: http://bugs.jython.org/issue1544

蝶舞 2024-10-03 07:44:52

看起来问题比我想象的更深 - 此论坛帖子 指示 urllib2直到 python 2.6 之后才实现 with,并且可能直到 3.1 才实现

Looks like the problem runs deeper than I thought - this forum thread indicates urllib2 doesn't implement with until after python 2.6, and possibly not until 3.1

掀纱窥君容 2024-10-03 07:44:52

您可以创建自己的通用 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 子句下发生的错误如何。

You could create your own generic URL opener:

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()

Then you could then use your syntax from your original question:

with urlopener(theURL) as sf:
    search_soup = BeautifulSoup.BeautifulSoup(sf.read())

This solution gives you a clean separation of concerns. You get a clean generic urlopener syntax that handles the complexities of properly closing the resource regardless of errors that occur underneath your with clause.

吃兔兔 2024-10-03 07:44:52

为什么不直接使用多个 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()

Why not just use multiple try/except blocks?

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文