2011-06-16 8 views
4

Pythonで他のライブラリからインポートされたライブラリの例外を処理する適切な方法は何ですか?Pythonで他のライブラリによってインポートされたライブラリから例外を処理するためのベストプラクティス?

たとえば、メインプログラムにインポートする「pycontrol」というライブラリがあります。 "pycontrol"は "suds"ライブラリをインポートします。 "suds"ライブラリは "urllib2"ライブラリをインポートします。私は、 "suds"ライブラリが "urllib2"を介してアクセスしているリモートリソースへの接続に問題がある場合、これらの例外が私のメインプログラムに流れ込むことに気付きました。

この時点で、urllib2とsudsを自分のグローバルな名前空間にインポートし、それらがスローされる典型的な例外をキャッチし、 "pycontrol"では処理されません。

これにどう対処するか他のベストプラクティスはありますか?

コードのスニペットは、(グローバル名前空間に泡やurllib2のインポートせずに)どのように見えるかの基本的な考え方:

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

私はあなたが答えだと思う:ここ

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." 

は、サンプルのトレースバックですあなた自身に疑問を抱くurllib2をインポートし、モジュール内で例外をキャッチします。

from urllib2 import URLError 

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

これは私が考え出しものです、それは未処理の例外が発生したときにPythonインタプリタは、標準エラー出力にスタックトレースをダンプし、プログラムを終了します(そしてやっている)。私は、これを処理するためのより「ピジョン(pythonic)」方法があると思いました。例外をスローしたものについて心配する必要はなく、私が使用しようとしているライブラリ(pycontrol)コールからスローされた例外をキャッチする必要があるはずです。 – perfectfromnowon

+0

あなたが対処する準備ができている例外はありません。たとえば、ValueErrorなどで何か役に立つことができない場合は、それを捕まえることに意味がありません。 –

0

なぜ特定の例外を捕捉する必要があるのですか?結局のところ、b = pc.BIGIP(...)から上げられた例外(URLErrorだけではない)を行えないということです。

私はお勧め:

import traceback 

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

もう一つのアイデア:なぜすべてで例外をキャッチしてわざわざ?

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

関連する問題