私はSaltStackのためのいくつかのetcdモジュールを書いていて、この奇妙な問題に遭遇しました。何とか私が例外をキャッチできないようにしています。具体的にはurllib3を中心にしているようです。なぜこのPython例外を捕まえられないのですか?
小さなスクリプト(ない塩):
import etcd
c = etcd.Client('127.0.0.1', 4001)
print c.read('/test1', wait=True, timeout=2)
そして、我々はそれを実行します。
[[email protected] utils]# /tmp/etcd_watch.py
Traceback (most recent call last):
File "/tmp/etcd_watch.py", line 5, in <module>
print c.read('/test1', wait=True, timeout=2)
File "/usr/lib/python2.6/site-packages/etcd/client.py", line 481, in read
timeout=timeout)
File "/usr/lib/python2.6/site-packages/etcd/client.py", line 788, in api_execute
cause=e
etcd.EtcdConnectionFailed: Connection to etcd failed due to ReadTimeoutError("HTTPConnectionPool(host='127.0.0.1', port=4001): Read timed out.",)
[OK]を、のは、その時間を浪費をキャッチしてみましょう:
#!/usr/bin/python
import etcd
c = etcd.Client('127.0.0.1', 4001)
try:
print c.read('/test1', wait=True, timeout=2)
except etcd.EtcdConnectionFailed:
print 'connect failed'
はそれを実行します。
を[[email protected] _modules]# /tmp/etcd_watch.py
connect failed
いいですね。それはすべて動作しているPythonです。だから何が問題なの?私は塩etcdモジュールでこれを持っている:
[[email protected] _modules]# cat sjmh.py
import etcd
def test():
c = etcd.Client('127.0.0.1', 4001)
try:
return c.read('/test1', wait=True, timeout=2)
except etcd.EtcdConnectionFailed:
return False
そして、私たちがいることを実行します。
[[email protected] _modules]# salt 'alpha' sjmh.test
alpha:
The minion function caused an exception: Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/salt/minion.py", line 1173, in _thread_return
return_data = func(*args, **kwargs)
File "/var/cache/salt/minion/extmods/modules/sjmh.py", line 5, in test
c.read('/test1', wait=True, timeout=2)
File "/usr/lib/python2.6/site-packages/etcd/client.py", line 481, in read
timeout=timeout)
File "/usr/lib/python2.6/site-packages/etcd/client.py", line 769, in api_execute
_ = response.data
File "/usr/lib/python2.6/site-packages/urllib3/response.py", line 150, in data
return self.read(cache_content=True)
File "/usr/lib/python2.6/site-packages/urllib3/response.py", line 218, in read
raise ReadTimeoutError(self._pool, None, 'Read timed out.')
ReadTimeoutError: HTTPConnectionPool(host='127.0.0.1', port=4001): Read timed out.
HRM、それは奇妙だが。 etcdの読み込みがetcd.EtcdConnectionFailedを返しているはずです。だから、それをさらに見てみましょう。当社のモジュールはこれです:
import etcd
def test():
c = etcd.Client('127.0.0.1', 4001)
try:
return c.read('/test1', wait=True, timeout=2)
except Exception as e:
return str(type(e))
そして、我々が得る:
[[email protected] _modules]# salt 'alpha' sjmh.test
alpha:
<class 'urllib3.exceptions.ReadTimeoutError'>
[OK]を、ので、我々はこの事をつかまえることができることを知っています。そして、私たちはReadTimeoutErrorを投げたことを知っているので、それを捕まえましょう。当社のモジュールの最新バージョン:
import etcd
import urllib3.exceptions
def test():
c = etcd.Client('127.0.0.1', 4001)
try:
c.read('/test1', wait=True, timeout=2)
except urllib3.exceptions.ReadTimeoutError as e:
return 'caught ya!'
except Exception as e:
return str(type(e))
そして、我々のテスト...
[[email protected] _modules]# salt 'alpha' sjmh.test
alpha:
<class 'urllib3.exceptions.ReadTimeoutError'>
Erは、待って、何?なぜ私たちはそれを捕まえなかったのですか?例外は正しく働いていますか?
どう
[[email protected] _modules]# cat sjmh.py
import etcd
import urllib3.exceptions
def test():
c = etcd.Client('127.0.0.1', 4001)
try:
c.read('/test1', wait=True, timeout=2)
except urllib3.exceptions.HTTPError:
return 'got you this time!'
..我々がしようとするとurllib3から基本クラスをキャッチした場合について
希望と..
[[email protected] _modules]# salt 'alpha' sjmh.test
alpha:
The minion function caused an exception: Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/salt/minion.py", line 1173, in _thread_return
return_data = func(*args, **kwargs)
File "/var/cache/salt/minion/extmods/modules/sjmh.py", line 7, in test
c.read('/test1', wait=True, timeout=2)
File "/usr/lib/python2.6/site-packages/etcd/client.py", line 481, in read
timeout=timeout)
File "/usr/lib/python2.6/site-packages/etcd/client.py", line 769, in api_execute
_ = response.data
File "/usr/lib/python2.6/site-packages/urllib3/response.py", line 150, in data
return self.read(cache_content=True)
File "/usr/lib/python2.6/site-packages/urllib3/response.py", line 218, in read
raise ReadTimeoutError(self._pool, None, 'Read timed out.')
ReadTimeoutError: HTTPConnectionPool(host='127.0.0.1', port=4001): Read timed out.
BLAST YEを祈ります!さて、違うetcd例外を返す別のメソッドを試してみましょう。当社のモジュールは、次のようになります。
import etcd
def test():
c = etcd.Client('127.0.0.1', 4001)
try:
c.delete('/')
except etcd.EtcdRootReadOnly:
return 'got you this time!'
そして、我々の実行:最終テストとして
[[email protected] _modules]# salt 'alpha' sjmh.test
alpha:
got you this time!
を、私はどちらかのストレートのpythonから、または塩のモジュールとして実行することができ、このモジュールは、作られました。 。パイソンを通じて
import etcd
import urllib3
def test():
c = etcd.Client('127.0.0.1', 4001)
try:
c.read('/test1', wait=True, timeout=2)
except urllib3.exceptions.ReadTimeoutError:
return 'got you this time!'
except etcd.EtcdConnectionFailed:
return 'cant get away from me!'
except etcd.EtcdException:
return 'oh no you dont'
except urllib3.exceptions.HTTPError:
return 'get back here!'
except Exception as e:
return 'HOW DID YOU GET HERE? {0}'.format(type(e))
if __name__ == "__main__":
print test()
:
[[email protected] _modules]# python ./sjmh.py
cant get away from me!
塩を通して:
[[email protected] _modules]# salt 'alpha' sjmh.test
alpha:
HOW DID YOU GET HERE? <class 'urllib3.exceptions.ReadTimeoutError'>
そこで、我々はそれをスローすることetcdから例外をキャッチすることができます。しかし、私たちは普通、python-etcdを孤独に走らせるときにurllib3 ReadTimeoutErrorを捕まえることができますが、塩を使って実行すると、ブランケット '例外'句を除いて、そのurllib3例外を捕まえることはできません。
私はそれを行うことができますが、私は本当に面白いのは、食べ物の塩が何をしているのか、例外が見つからないようにしています。私はPythonを使って作業するときこれまでこれを見たことがないので、どうやって起こっているのか、どうすれば回避できるのかが不思議です。
編集:
私は最後にそれをキャッチすることができました。
import etcd
import urllib3.exceptions
from urllib3.exceptions import ReadTimeoutError
def test():
c = etcd.Client('127.0.0.1', 4001)
try:
c.read('/test1', wait=True, timeout=2)
except urllib3.exceptions.ReadTimeoutError:
return 'caught 1'
except urllib3.exceptions.HTTPError:
return 'caught 2'
except ReadTimeoutError:
return 'caught 3'
except etcd.EtcdConnectionFailed as ex:
return 'cant get away from me!'
except Exception as ex:
return 'HOW DID YOU GET HERE? {0}'.format(type(ex))
if __name__ == "__main__":
print test()
そして実行すると:
[[email protected] _modules]# salt 'alpha' sjmh.test
alpha:
caught 3
それはまだかかわらず、意味がありません。私が例外を知っていることから、リターンは「捕まえられる」べきである。完全なクラス名を使用するのではなく、例外の名前を直接インポートする必要があるのはなぜですか?
詳細編集!
したがって、2つのクラスの比較を追加すると、「False」が生成されます。これは、except節が機能していないため、同じではない可能性があるためです。
私はc.read()を呼び出す直前に次のスクリプトを追加しました。
log.debug(urllib3.exceptions.ReadTimeoutError.__module__)
log.debug(ReadTimeoutError.__module__)
そして今、私は、ログにこれを取得する:だから
[DEBUG ] requests.packages.urllib3.exceptions
[DEBUG ] urllib3.exceptions
、それは道を捕まるされる理由であると表示されます。これはちょうどetcdをダウンロードして、ライブラリを要求し、このような何かを行うことによっても再現可能です:
#!/usr/bin/python
#import requests
import etcd
c = etcd.Client('127.0.0.1', 4001)
c.read("/blah", wait=True, timeout=2)
あなたが上げ「正しい」の例外を取得してしまいます - etcd.EtcdConnectionFailed。ただし、 '要求'のコメントを外して、urllib3.exceptions.ReadTimeoutErrorになります。これは、etcdが例外をキャッチしなくなったためです。
したがって、リクエストをインポートすると、urllib3例外が書き換えられ、それをキャッチしようとしている他のモジュールは失敗します。また、新しいバージョンのリクエストにはこの問題はないようです。
'' Hrm、それは奇妙です。etcdの読み込みはetcd.EtcdConnectionFailed "を返しているはずです。奇妙なことではない。'ReadTimeoutError'は、データを受信する時間が下位プロトコルレベルで終了したという事実を記述します。 'ConnectionFailed'は、クライアントがリモートサービスに接続できなかった事実を記述しています(いくつかの理由で)。これらは、あなたが経験している2つの異なる条件です。特に、リモートサーバーのリソースが少なく、速度が遅い場合は、ネットワーキングでよく使用されます。 – Pynchia
Pynchia、私はそれが返されているはずでした。なぜなら一般的にpython-etcd 0.4.2では、待ち時間が過ぎるとetcd.EtcdConnectionFailedが発生するからです。ローカルのetcdのインスタンスで、etcdがアップしていることを確認しました。また、最後のスクリプトで示されているように、ネットワーキング以外の何かが進行中です。 – sjmh
ああはい。それがConnectionが失敗するもう一つの理由です。しかし、あなたのケースでは、タイムアウトによりReadが失敗しています。つまり、ライブラリは奇妙な動作をするかもしれません。 – Pynchia