Fangen Fehler im Generator und weiter danach

Ich habe einen Iterator, der seit mehreren Tagen laufen soll. Ich möchte, dass Fehler gefangen und gemeldet werden, und dann möchte ich, dass der Iterator weiter geht. Oder der ganze Prozess kann beginnen.

Hier ist die Funktion:

def get_units(self, scraper): units = scraper.get_units() i = 0 while True: try: unit = units.next() except StopIteration: if i == 0: log.error("Scraper returned 0 units", {'scraper': scraper}) break except: traceback.print_exc() log.warning("Exception occurred in get_units", extra={'scraper': scraper, 'iteration': i}) else: yield unit i += 1 

Weil scraper eine von vielen Varianten von Code sein könnte, kann man nicht vertrauen und ich will die Fehler dort nicht behandeln.

Aber wenn ein Fehler in units.next() auftritt, units.next() das Ganze auf. Ich vermute, weil ein Iterator eine StopIteration wirft, wenn einer der Iterationen fehlschlägt.

Hier ist die Ausgabe (nur die letzten Zeilen)

 [2012-11-29 14:11:12 /home/amcat/amcat/scraping/scraper.py:135 DEBUG] Scraping unit <Element div at 0x4258c710> [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article [2012-11-29 14:11:13 /home/amcat/amcat/scraping/scraper.py:138 DEBUG] .. yields article Counter-Strike: Global Offensive Update Released Traceback (most recent call last): File "/home/amcat/amcat/scraping/controller.py", line 101, in get_units unit = units.next() File "/home/amcat/amcat/scraping/scraper.py", line 114, in get_units for unit in self._get_units(): File "/home/amcat/scraping/games/steamcommunity.py", line 90, in _get_units app_doc = self.getdoc(url,urlencode(form)) File "/home/amcat/amcat/scraping/scraper.py", line 231, in getdoc return self.opener.getdoc(url, encoding) File "/home/amcat/amcat/scraping/htmltools.py", line 54, in getdoc response = self.opener.open(url, encoding) File "/usr/lib/python2.7/urllib2.py", line 406, in open response = meth(req, response) File "/usr/lib/python2.7/urllib2.py", line 519, in http_response 'http', request, response, code, msg, hdrs) File "/usr/lib/python2.7/urllib2.py", line 444, in error return self._call_chain(*args) File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain result = func(*args) File "/usr/lib/python2.7/urllib2.py", line 527, in http_error_default raise HTTPError(req.get_full_url(), code, msg, hdrs, fp) HTTPError: HTTP Error 500: Internal Server Error [2012-11-29 14:11:14 /home/amcat/amcat/scraping/controller.py:110 WARNING] Exception occurred in get_units ...code ends... 

Also, wie kann ich verhindern, dass die Iteration aufhört, wenn ein Fehler auftritt?

EDIT: Hier ist der Code innerhalb get_units ()

 def get_units(self): """ Split the scraping job into a number of 'units' that can be processed independently of each other. @return: a sequence of arbitrary objects to be passed to scrape_unit """ self._initialize() for unit in self._get_units(): yield unit 

Und hier ist eine vereinfachte _get_units ():

 INDEX_URL = "http://www.steamcommunity.com" def _get_units(self): doc = self.getdoc(INDEX_URL) #returns a lxml.etree document for a in doc.cssselect("div.discussion a"): link = a.get('href') yield link 

EDIT: Frage Followup: Ändern Sie jede for-Schleife in einer Funktion, um Fehlerbehandlung automatisch nach jeder fehlgeschlagenen Iteration ausgeführt zu haben

    One Solution collect form web for “Fangen Fehler im Generator und weiter danach”

    StopIteration wird durch die next() Methode eines Generators angehoben, wenn kein nächster Artikel mehr vorhanden ist. Es hat nichts mit Fehlern im Generator / Iterator zu tun.

    Eine andere Sache zu beachten ist, dass je nach Art des Iterators, kann es nicht möglich sein, nach einer Ausnahme wieder aufzunehmen. Wenn der Iterator ein Objekt mit einer next Methode ist, wird es funktionieren. Allerdings, wenn es tatsächlich ein Generator ist, wird es nicht.

    Soweit ich sagen kann, ist dies der einzige Grund, warum Ihre Iteration nicht nach einem Fehler von units.next() fortgesetzt wird. Ie units.next() scheitert, und das nächste Mal, wenn du es nennst, kann es nicht wieder aufnehmen und es sagt, dass es durch das Werfen einer StopIteration Ausnahme gemacht wird.

    Grundsätzlich musst du uns den Code in scraper.get_units() damit wir verstehen können, warum die Schleife nach einem Fehler innerhalb einer einzigen Iteration nicht fortfahren kann. Wenn get_units() als Generatorfunktion implementiert ist, ist es klar. Wenn nicht, könnte es etwas anderes sein, das verhindert, dass es wieder aufgenommen wird.

    UPDATE: erklären, was eine Generatorfunktion ist:

     class Scraper(object): def get_units(self): for i in some_stuff: bla = do_some_processing() bla *= 2 # random stuff yield bla 

    Nun, wenn du Scraper().get_units() , anstatt die gesamte Funktion Scraper().get_units() , gibt es ein Generatorobjekt zurück. Anrufen next() auf, wird die Ausführung auf den ersten yield . Etc. Nun, wenn ein Fehler aufgetreten ist, wird es in get_units , wird es verdorben werden, so zu sagen, und das nächste Mal, wenn Sie als next() anrufen, wird es StopIteration erhöhen, so als ob es aus Artikeln StopIteration , um Ihnen zu geben.

    Lesen von http://www.dabeaz.com/generators/ (und http://www.dabeaz.com/coroutines/ ) dringend empfohlen.

    UPDATE2: Eine mögliche Lösung https://gist.github.com/4175802

    Python ist die beste Programmiersprache der Welt.