2010-10-07 8 views
7

Ich habe folgenden Code in einem Python-SkriptSchließen von Dateien ordnungsgemäß mit urllib2.urlopen geöffnet()

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 

ich betroffen bin, denn wenn ich auf sf.read() einen Fehler auftreten, dann wird sf.clsoe() nicht genannt. Ich habe versucht, sf.close() in einem finally Block, aber wenn es eine Ausnahme auf urlopen() gibt, dann gibt es keine Datei zu schließen, und ich stoße auf eine Ausnahme im finally Block!

So dann habe ich versucht

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 

aber hob einen ungültigen Syntaxfehler auf der with... Linie. Wie kann ich am besten damit umgehen, ich fühle mich dumm!

Wie commen darauf hingewiesen haben, ich bin mit PyS60 dem Python ist 2.5.4

+2

Die Anweisung "with" steht nur in Python 2.6 oder in 2.5 zur Verfügung, wenn Sie '__future__ import with_statement' an den Anfang Ihrer Datei setzen. Ich erinnere mich nicht genau, was Python-Version PyS60 implementiert, aber es könnte 2,5 sein? –

+0

ist es 2.5.4. der Import ist ein guter Punkt :) – Habbie

Antwort

6

Warum nicht versuchen, nur sf zu schließen, und vorbei, wenn es nicht vorhanden ist ?

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

Wusste, dass ich etwas offensichtliche, verschachtelte trys fehlte! Ihre Lösung ist sehr elegant, danke! – fearoffours

0

Sieht aus wie das Problem geht tiefer, als ich dachte - this forum thread zeigt urllib2 nicht with 2.6 und möglicherweise erst nach python implementiert nicht bis 3.1

+0

Das ist wahr. Ich bin auf Python 2.7 (Kommentierung im Jahr 2013) und es scheint nicht zu funktionieren, also schreibe ich etwas neu geschrieben ursprünglich für Python3 in Python2 und ich bin gezwungen, alle meine 'mit urllib.urlopen (source) als neu zu schreiben f: 'Aussagen. – erewok

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

würde ich contextlib.closing verwenden (in Kombination mit von __future__ Import with_statement für alte Python-Versionen):

from contextlib import closing 

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

Oder, wenn Sie die mit Anweisung vermeiden wollen:

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

Nicht ganz so elegant aber.

0

Sie könnten Ihre eigene generische URL Opener erstellen:

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

Diese Lösung bietet Ihnen eine saubere Trennung von Bedenken:

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

Dann sind Sie dann Ihre Syntax von Ihrer ursprünglichen Frage verwenden könnte. Sie erhalten eine saubere generische URLopener-Syntax, die die Komplexität des ordnungsgemäßen Schließens der Ressource behandelt, unabhängig von Fehlern, die unter Ihrer with-Klausel auftreten.

0

Warum nicht einfach mehrere try/except Blöcke verwenden?

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

Wenn urlopen() eine Ausnahme hat, es zu fangen und die Nähe der Ausnahme nennen() -Funktion, wie folgt aus:

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) 

die Ausnahme ist auch eine vollständige Response-Objekt, können Sie dieses Problem sehen message: http://bugs.jython.org/issue1544

Verwandte Themen