简体   繁体   English

isinstance()意外返回False

[英]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.exceptionssys.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM