2012-11-25 34 views
1

我有兩個功能可以正常工作,但是當我將它們嵌套在一起時似乎會失效。什麼是pythonic方式來捕捉錯誤,並繼續在這個循環?

def scrape_all_pages(alphabet): 
    pages = get_all_urls(alphabet) 
    for page in pages: 
     scrape_table(page) 

我想系統地刮一些搜索結果。因此get_all_pages()會爲字母表中的每個字母創建一個URL列表。有時候有成千上萬的頁面,但工作得很好。然後,對於每個頁面,scrape_table只是對我感興趣的表格進行刮擦。這也可以正常工作。我可以運行整個事情,它工作正常,但我在Scraperwiki工作,如果我設置它運行並走開,它總是給我一個「列表索引超出範圍」的錯誤。這絕對是scraperwiki中的一個問題,但我想找到解決問題的方法,在遇到它們時添加一些try/except子句和記錄錯誤。例如:

def scrape_all_pages(alphabet): 
    try: 
     pages = get_all_urls(alphabet) 
    except: 
     ## LOG THE ERROR IF THAT FAILS. 
    try: 
     for page in pages: 
      scrape_table(page) 
    except: 
     ## LOG THE ERROR IF THAT FAILS 

雖然我一直無法弄清楚如何統一記錄錯誤。而且,上面看起來笨重,根據我的經驗,當東西看起來笨重時,Python有更好的方法。有沒有更好的辦法?因爲他們是所謂全部來自異常繼承

def scrape_all_pages(alphabet): 
    try: 
     pages = get_all_urls(alphabet) 
     for page in pages: 
      scrape_table(page) 
    except OutOfRangeError as error: 
     # Will only catch OutOfRangeError 
     print error 
    except Exception as error: 
     # Will only catch any other exception 
     print error 

鳳雲類型異常將捕獲所有錯誤:

回答

0

這是一個好辦法,但。您不應該只使用except子句,您必須指定您嘗試捕獲的異常的類型。您也可以捕捉錯誤並繼續循環。

def scrape_all_pages(alphabet): 
    try: 
     pages = get_all_urls(alphabet) 
    except IndexError: #IndexError is an example 
     ## LOG THE ERROR IF THAT FAILS. 

    for page in pages: 
     try: 
      scrape_table(page) 
     except IndexError: # IndexError is an example 
      ## LOG THE ERROR IF THAT FAILS and continue this loop 
+0

我實際上已經完成了類似'except Exception,e:print str(e)'這樣的東西 - 仍然不那麼優雅,但它幫助我消除了錯誤。 – Amanda

2

您可以指定某一類型的異常捕捉和一個變量來保存異常實例。

這是我知道捕捉錯誤的唯一途徑。

+0

您還可以通過上下文管理器捕獲錯誤。我在這裏發佈了一個例子。 –

0

也許在錯誤日誌中的每次迭代,這樣在一個迭代的錯誤不會破壞你的循環:

for page in pages: 
    try: 
     scrape_table(page) 
    except: 
     #open error log file for append: 
     f=open("errors.txt","a") 
     #write error to file: 
     f.write("Error occured\n") # some message specific to this iteration (page) should be added here... 
     #close error log file: 
     f.close() 
2

環繞周圍上下文管理日誌信息,這樣雖然你可以很容易地改變細節,以滿足您的要求:

import traceback 

# This is a context manager 
class LogError(object): 
    def __init__(self, logfile, message): 
     self.logfile = logfile 
     self.message = message 
    def __enter__(self): 
     return self 
    def __exit__(self, type, value, tb): 
     if type is None or not issubclass(type, Exception): 
      # Allow KeyboardInterrupt and other non-standard exception to pass through 
      return 

     self.logfile.write("%s: %r\n" % (self.message, value)) 
     traceback.print_exception(type, value, tb, file=self.logfile) 
     return True # "swallow" the traceback 

# This is a helper class to maintain an open file object and 
# a way to provide extra information to the context manager. 
class ExceptionLogger(object): 
    def __init__(self, filename): 
     self.logfile = open(filename, "wa") 
    def __call__(self, message): 
     # override function() call so that I can specify a message 
     return LogError(self.logfile, message) 

的關鍵部分是,__exit__可以返回「真」,在該例外情況被忽略,並且該程序繼續進行。代碼還需要小心一點,因爲可能會引發KeyboardInterrupt(control-C),SystemExit或其他非標準異常,以及實際上希望程序停止的位置。

您可以使用上面的代碼是這樣的:

elog = ExceptionLogger("/dev/tty") 

with elog("Can I divide by 0?"): 
    1/0 

for i in range(-4, 4): 
    with elog("Divisor is %d" % (i,)): 
     print "5/%d = %d" % (i, 5/i) 

片斷代碼給我的輸出:

Can I divide by 0?: ZeroDivisionError('integer division or modulo by zero',) 
Traceback (most recent call last): 
    File "exception_logger.py", line 24, in <module> 
    1/0 
ZeroDivisionError: integer division or modulo by zero 
5/-4 = -2 
5/-3 = -2 
5/-2 = -3 
5/-1 = -5 
Divisor is 0: ZeroDivisionError('integer division or modulo by zero',) 
Traceback (most recent call last): 
    File "exception_logger.py", line 28, in <module> 
    print "5/%d = %d" % (i, 5/i) 
ZeroDivisionError: integer division or modulo by zero 
5/1 = 5 
5/2 = 2 
5/3 = 1 

我認爲它也很容易看到一個會如何修改代碼來處理僅記錄IndexError異常,或甚至傳入基本異常類型來捕獲。

0

它能夠更好地把它寫這樣的:

try: 
     pages = get_all_urls(alphabet) 
    except IndexError: 
     ## LOG THE ERROR IF THAT FAILS. 
    for page in pages: 
     try: 
      scrape_table(page) 
     except IndexError: 
      continue ## this will bring you to the next item in for 
     ## LOG THE ERROR IF THAT FAILS