2011-06-16 76 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