[英]isinstance() unexpectedly returning False
I am using the kubernetes python client . 我正在使用kubernetes python客户端 。 In the event that kubernetes isn't available when my code starts up, I would like to retry the connection. 如果我的代码启动时kubernetes不可用,我想重试连接。
When the client is unable to connect, it throws what appears to be a urllib3.exceptions.MaxRetryError
exception, so I started with something like this: 当客户端无法连接时,它会抛出看似urllib3.exceptions.MaxRetryError
异常的内容,所以我开始使用以下内容:
import time
import urllib3
import kubernetes
kubernetes.config.load_kube_config()
api = kubernetes.client.CoreV1Api()
while True:
try:
w = kubernetes.watch.Watch()
for event in w.stream(api.list_pod_for_all_namespaces):
print event
except urllib3.exceptions.HTTPError:
print('retrying in 1 second')
time.sleep(1)
But that completely fails; 但那完全失败了; it acts like there is no except
statement and bails out with: 它的行为就像没有except
声明和保释:
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='192.168.122.140', port=8443): Max retries exceeded with url: /api/v1/pods?watch=True (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x2743110>: Failed to establish a new connection: [Errno 111] Connection refused',))
I thought maybe I didn't understand inheritance as well as I thought, so I replace the above with: 我想也许我不理解继承和我想的,所以我用以下内容替换上面的:
except urllib3.exceptions.MaxRetryError:
print('retrying in 1 second')
time.sleep(1)
Which fails in the same way. 哪个失败的方式相同。 In an effort to figure out what was going on, I added a catch-all except
and invoked pdb: 为了弄清楚发生了什么,我添加了一个catch-all except
和调用pdb:
except Exception as err:
import pdb; pdb.set_trace()
And from the pdb
prompt, we can see: 从pdb
提示符中,我们可以看到:
(Pdb) type(err)
<class 'urllib3.exceptions.MaxRetryError'>
...which looks fine, as does the mro: ...看起来很好,和mro一样:
(Pdb) import inspect
(Pdb) inspect.getmro(err.__class__)
(<class 'urllib3.exceptions.MaxRetryError'>, <class 'urllib3.exceptions.RequestError'>, <class 'urllib3.exceptions.PoolError'>, <class 'urllib3.exceptions.HTTPError'>, <type 'exceptions.Exception'>, <type 'exceptions.BaseException'>, <type 'object'>)
But despite all that: 但尽管如此:
(Pdb) isinstance(err, urllib3.exceptions.MaxRetryError)
False
And all the paths look reasonable: 并且所有路径看起来都合理:
(Pdb) urllib3.__file__
'/usr/lib/python2.7/site-packages/urllib3/__init__.pyc'
(Pdb) kubernetes.client.rest.urllib3.__file__
'/usr/lib/python2.7/site-packages/urllib3/__init__.pyc'
So...what the actual what is going on here? 那么......实际发生了什么?
Update 更新
Here is the full stack trace: 这是完整的堆栈跟踪:
Traceback (most recent call last):
File "testkube.py", line 13, in <module>
for event in w.stream(api.list_pod_for_all_namespaces):
File "/usr/lib/python2.7/site-packages/kubernetes/watch/watch.py", line 116, in stream
resp = func(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/kubernetes/client/apis/core_v1_api.py", line 14368, in list_pod_for_all_namespaces
(data) = self.list_pod_for_all_namespaces_with_http_info(**kwargs)
File "/usr/lib/python2.7/site-packages/kubernetes/client/apis/core_v1_api.py", line 14464, in list_pod_for_all_namespaces_with_http_info
collection_formats=collection_formats)
File "/usr/lib/python2.7/site-packages/kubernetes/client/api_client.py", line 335, in call_api
_preload_content, _request_timeout)
File "/usr/lib/python2.7/site-packages/kubernetes/client/api_client.py", line 148, in __call_api
_request_timeout=_request_timeout)
File "/usr/lib/python2.7/site-packages/kubernetes/client/api_client.py", line 371, in request
headers=headers)
File "/usr/lib/python2.7/site-packages/kubernetes/client/rest.py", line 250, in GET
query_params=query_params)
File "/usr/lib/python2.7/site-packages/kubernetes/client/rest.py", line 223, in request
headers=headers)
File "/usr/lib/python2.7/site-packages/urllib3/request.py", line 66, in request
**urlopen_kw)
File "/usr/lib/python2.7/site-packages/urllib3/request.py", line 87, in request_encode_url
return self.urlopen(method, url, **extra_kw)
File "/usr/lib/python2.7/site-packages/urllib3/poolmanager.py", line 321, in urlopen
response = conn.urlopen(method, u.request_uri, **kw)
File "/usr/lib/python2.7/site-packages/urllib3/connectionpool.py", line 668, in urlopen
**response_kw)
File "/usr/lib/python2.7/site-packages/urllib3/connectionpool.py", line 668, in urlopen
**response_kw)
File "/usr/lib/python2.7/site-packages/urllib3/connectionpool.py", line 668, in urlopen
**response_kw)
File "/usr/lib/python2.7/site-packages/urllib3/connectionpool.py", line 639, in urlopen
_stacktrace=sys.exc_info()[2])
File "/usr/lib/python2.7/site-packages/urllib3/util/retry.py", line 388, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='192.168.122.140', port=8443): Max retries exceeded with url: /api/v1/pods?watch=True (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x3d16110>: Failed to establish a new connection: [Errno 111] Connection refused',))
Your code has an indirect dependency on the requests
package, and the requests
package has a strange submodule called requests.packages
. 您的代码对requests
包具有间接依赖性,而requests
包具有一个名为requests.packages
的奇怪子模块。 This used to contain copied source code from a number of dependencies, including urllib3
, but they stopped doing that. 这用于包含来自许多依赖项的复制源代码,包括urllib3
,但它们停止这样做。 They wanted to keep requests.packages
around for backward compatibility, though, so now they're doing something weird. 他们希望保留requests.packages
以便向后兼容,所以现在他们做了一些奇怪的事情。
Instead of requests.packages
including a complete copy of the urllib3
source code, it now imports urllib3
and sets sys.modules['requests.packages.urllib3'] = urllib3
. 代替requests.packages
包括的完整副本urllib3
源代码,它现在进口urllib3
并设置sys.modules['requests.packages.urllib3'] = urllib3
。 Depending on the requests
version, it may set a number of other sys.modules
entries, too; 根据requests
版本,它也可以设置许多其他sys.modules
条目; for example, as of requests 2.18.4 , the source code does 例如,从请求2.18.4开始 ,源代码就是这样做的
for package in ('urllib3', 'idna', 'chardet'):
locals()[package] = __import__(package)
# This traversal is apparently necessary such that the identities are
# preserved (requests.packages.urllib3.* is urllib3.*)
for mod in list(sys.modules):
if mod == package or mod.startswith(package + '.'):
sys.modules['requests.packages.' + mod] = sys.modules[mod]
but in 2.17.0 , it does 但在2.17.0中确实如此
import urllib3
sys.modules['requests.packages.urllib3'] = urllib3
import idna
sys.modules['requests.packages.idna'] = idna
import chardet
sys.modules['requests.packages.chardet'] = chardet
This code interacts badly with submodules of the imported packages. 此代码与导入的包的子模块严重交互。 If some code tries to do import requests.packages.urllib3.exceptions
and Python doesn't find a sys.modules['requests.packages.urllib3.exceptions']
entry, Python will recreate the urllib3.exceptions
module and set urllib3.exceptions
and sys.modules['requests.packages.urllib3.exceptions']
to the new module (but it won't touch sys.modules['urllib3.exceptions']
. This will generate new copies of the classes involved, causing your error. 如果某些代码尝试执行import requests.packages.urllib3.exceptions
并且Python找不到sys.modules['requests.packages.urllib3.exceptions']
条目,Python将重新创建 urllib3.exceptions
模块并设置urllib3.exceptions
和sys.modules['requests.packages.urllib3.exceptions']
到新模块(但它不会触及sys.modules['urllib3.exceptions']
。这将生成所涉及的类的新副本,导致您的错误。
A related problem with the same cause was reported back in May, leading to the new code shown in 2.18.4. 5月份报告了一个相同原因的相关问题,导致2.18.4中显示的新代码。 2.18.4 shouldn't cause the specific problems you're seeing, but it's still fragile, because if any submodules of urllib3
aren't yet loaded at the time requests.packages
screws with sys.modules
, those submodules will exhibit the same problems you've seen today. 2.18.4应该不会造成您看到的具体问题,但它仍然是脆弱的,因为如果任何子模块urllib3
尚未加载的时候requests.packages
螺钉sys.modules
,那些子模块会出现相同的问题你今天见过。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.