2010-10-07 25 views
7

我有一個python腳本關閉文件與urllib2.urlopen正常打開()

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這是蟒蛇2.5.4

+2

「with」語句僅在Python 2.6中可用,如果將'from __future__ import with_statement'放在文件的頂部,則該語句只能在2.5中使用。我不太清楚Python版本PyS60實現的是什麼,但它可能是2.5? – 2010-10-07 10:47:28

+0

它是2.5.4。進口是一個好點:) – Habbie 2010-10-07 10:48:56

回答

6

爲什麼不嘗試關閉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 
+0

知道我錯過了明顯的東西,嵌套的托盤!您的解決方案非常優雅,謝謝! – fearoffours 2010-10-07 12:13:01

0

貌似運行的問題比我想象的更深 - this forum thread表示的urllib2沒有實現with直到蟒蛇2.6後,可能直到3.1

+0

這是真的。我在Python 2.7(2013年評論),它似乎並沒有工作,所以我重寫了原來爲Python3編寫的Python2中的東西,我不得不將所有'urllib.urlopen(source)'重寫爲f:'語句。 – erewok 2013-09-23 20:04:29

8
finally: 
    if sf: sf.close() 
16

我會用contextlib.closing(結合從__future__進口with_statement舊的Python版本):

from contextlib import closing 

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

或者,如果你想避免與聲明:

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

雖然不盡如人意。

0

你可以創建自己的通用網址揭幕戰:

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子句下發生的錯誤。

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

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