2011-06-16 92 views
4

在Python中處理由其他庫導入的庫的異常的適當方式是什麼?處理Python中其他庫導入庫的異常的最佳實踐?

例如,我有一個名爲「pycontrol」的庫,我將其導入到主程序中。 「pycontrol」導入「泡沫」庫。 「suds」庫反過來導入「urllib2」庫。我注意到,當「suds」庫無法連接到遠程資源時,它通過「urllib2」訪問,這些異常流向我的主程序。

在這一點上,我最好的猜測是將urllib2和suds導入到我的全局名稱空間中,並捕獲由它們拋出並且不在「pycontrol」中處理的典型異常。

有沒有其他的最佳做法,如何可以接近這個?

什麼代碼段的樣子(沒有進口肥皂水或urllib2的成全局命名空間)的基本思想:

import pycontrol.pycontrol as pc 

    print "Connecting to iControl API on LTM %s..." % ltm 
    try: 
     b = pc.BIGIP(hostname=ltm, username=user, password=pw, 
      wsdls=wsdl_list, fromurl=True, 
      debug=soap_debug) 
    except (<whattocatch>), detail: 
     print "Error: could not connect to iControl API on LTM %s... aborting!" % ltm 
     print "Details: %s" % detail 
     exitcode = 1 
    else: 
     print "Connection successfully established." 

以下是樣本追蹤:

Connecting to iControl API on LTM s0-bigip1-lb2.lab.zynga.com... 
Traceback (most recent call last): 
    File "./register.py", line 507, in <module> 
    main() 
    File "./register.py", line 415, in main 
    b = build_bigip_object(ltm, user, pw, WSDLS, soap_debug = False) 
    File "./register.py", line 85, in build_bigip_object 
    debug=soap_debug) 
    File "build/bdist.macosx-10.6-universal/egg/pycontrol/pycontrol.py", line 81, in __init__ 
    File "build/bdist.macosx-10.6-universal/egg/pycontrol/pycontrol.py", line 103, in _get_clients 
    File "build/bdist.macosx-10.6-universal/egg/pycontrol/pycontrol.py", line 149, in _get_suds_client 
    File "/Library/Python/2.6/site-packages/suds/client.py", line 111, in __init__ 
    self.wsdl = reader.open(url) 
    File "/Library/Python/2.6/site-packages/suds/reader.py", line 136, in open 
    d = self.fn(url, self.options) 
    File "/Library/Python/2.6/site-packages/suds/wsdl.py", line 136, in __init__ 
    d = reader.open(url) 
    File "/Library/Python/2.6/site-packages/suds/reader.py", line 73, in open 
    d = self.download(url) 
    File "/Library/Python/2.6/site-packages/suds/reader.py", line 88, in download 
    fp = self.options.transport.open(Request(url)) 
    File "/Library/Python/2.6/site-packages/suds/transport/https.py", line 60, in open 
    return HttpTransport.open(self, request) 
    File "/Library/Python/2.6/site-packages/suds/transport/http.py", line 62, in open 
    return self.u2open(u2request) 
    File "/Library/Python/2.6/site-packages/suds/transport/http.py", line 118, in u2open 
    return url.open(u2request, timeout=tm) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib2.py", line 383, in open 
    response = self._open(req, data) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib2.py", line 401, in _open 
    '_open', req) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib2.py", line 361, in _call_chain 
    result = func(*args) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib2.py", line 1138, in https_open 
    return self.do_open(httplib.HTTPSConnection, req) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib2.py", line 1105, in do_open 
    raise URLError(err) 
urllib2.URLError: <urlopen error [Errno 8] nodename nor servname provided, or not known> 

回答

2

我想你回答你質疑自己。導入urllib2並捕獲模塊中的異常。

from urllib2 import URLError 

try: 
    # something 
except URLError, e: 
    # Do something in case of error. 
+0

這是我想通(並一直在做)。我想我認爲有一種更「pythonic」的方式來處理這個問題。看起來我應該也可以不用擔心拋出異常的情況,只需捕獲我試圖使用的庫(pycontrol)調用引發的任何異常。 – perfectfromnowon 2011-06-18 05:22:07

+0

不完全 - 只會捕捉您準備處理的異常情況。如果你不能對ValueError做任何有用的事情,那麼捕獲它就沒有意義。 – 2011-07-29 22:23:58

0

爲什麼你需要捕捉特定的異常呢?畢竟,從b = pc.BIGIP(...)提出的任何異常(不僅僅是URLError)意味着你不能繼續。

我建議:

import traceback 

try: 
    b = pc.BIGIP(...) 
except: 
    traceback.print_exc() 
    exitcode = 1 
else: 
    do_something_with_connection(b) 

另一個想法:爲什麼在所有的捕捉異常費心呢? Python解釋器將轉儲堆棧跟蹤到stderr和退出程序時遇到未處理的異常:

b = bc.BIGIP(...) 
do_something_with_connection(b) 

或者,如果你需要寫一個錯誤日誌:

import logging 
import sys 

def main(): 
    b = bc.BIGIP(...) 
    do_something_with_connection(b) 

if __name__ == "__main__": 
    try: 
     main() 
    except: 
     logging.exception("An unexpected error occured") 
     sys.exit(1) 
+0

感謝您的寶貴意見。異常本身實際上就有關遠程API發生的事情傳達了有用的信息。有時候異常實際上是非致命的,我只需要在遠程API操作失敗時做一些合乎邏輯的事情。 – perfectfromnowon 2011-06-18 05:19:21