Requests: https:// 不适用于 Python 3.6

创建于 2016-12-07  ·  16评论  ·  资料来源: psf/requests

请求 https:// url 时, request方法陷入无限递归。

问题是python/ssl.py这种方法。

    @options.setter
    def options(self, value):
        super(SSLContext, SSLContext).options.__set__(self, value)

将这一行引入 python 的提交是https://hg.python.org/cpython/rev/c32e9f9b00f7。

实际错误如下所示:

  File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 501, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.6/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/requests/adapters.py", line 423, in send
    timeout=timeout
  File "/usr/local/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 594, in urlopen
    chunked=chunked)
  File "/usr/local/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 350, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 835, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.6/site-packages/requests/packages/urllib3/connection.py", line 311, in connect
    cert_reqs=resolve_cert_reqs(self.cert_reqs),
  File "/usr/local/lib/python3.6/site-packages/requests/packages/urllib3/util/ssl_.py", line 264, in create_urllib3_context
    context.options |= options
  File "/usr/local/lib/python3.6/ssl.py", line 459, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/usr/local/lib/python3.6/ssl.py", line 459, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/usr/local/lib/python3.6/ssl.py", line 459, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  [Previous line repeated 316 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object

使用python 3.6.0b4

最有用的评论

Requests 在 gevent 和猴子补丁方面存在一些问题,因为它在导入时对 select 模块执行特征检测。 未来的版本将使用更新的 urllib3 更新它,其中包含针对此问题的修复程序,但同时应在导入请求之前应用 gevent 的猴子补丁。

所有16条评论

这听起来像是标准库中的一个错误,实际上:它们似乎在直接设置选项时引入了无限递归。 @蒂兰?

我无法在我的机器上重现这个问题(来自最新的 hg 3.6 分支的 Python)

$ ./python 
Python 3.6.0+ (3.6:c4f39b6f3176, Dec  7 2016, 21:55:50) 
[GCC 6.2.1 20160916 (Red Hat 6.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ctx = ssl.SSLContext(ssl.PROTOCOL_TLS)
>>> ctx.options |= 5
>>> class MySSLContext(ssl.SSLContext):
...     pass
... 
>>> ctx = MySSLContext(ssl.PROTOCOL_TLS)
>>> ctx.options |= 5

我只是尝试从请求端重现它; 我无法在 3.6.0b4 或 3.6.0rc1 上击中它:

$ python
Python 3.6.0b4 (v3.6.0b4:18496abdb3d5, Nov 21 2016, 20:44:47)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.get('https://github.com/kennethreitz/requests/issues/3752')
<Response [200]>
$ python
Python 3.6.0rc1 (v3.6.0rc1:29a273eee9a5, Dec  6 2016, 16:24:13)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.get('https://github.com/kennethreitz/requests/issues/3752')
<Response [200]>

它可能是特定于平台或 URL 的东西吗?

(就我而言,OS X 10.12.1、16B2659)

请求也适用于 hg 的 Python 3.6.0:

$ ./python -m venv venv
$ venv/bin/pip install requests
Collecting requests
  Using cached requests-2.12.3-py2.py3-none-any.whl
Installing collected packages: requests
Successfully installed requests-2.12.3
$ venv/bin/python
Python 3.6.0+ (3.6:c4f39b6f3176, Dec  7 2016, 21:55:50) 
[GCC 6.2.1 20160916 (Red Hat 6.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.get('https://www.python.org')
<Response [200]>

好的,现在这看起来像是“无法重现”的情况。 可能值得查看您的安装@juokaz ,似乎有点行为不端。

在进一步调试之后,我能够将它重现为gevent问题(这是我使用它的上下文)。

我猜我将不得不把它带到 gevent 人那里看看? 谢谢大家的调查。

root<strong i="8">@8042e3f57981</strong>:/app# python
Python 3.6.0b4 (default, Nov 23 2016, 21:34:29)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import gevent.monkey
>>> gevent.monkey.patch_all()
>>>
>>> from requests.packages.urllib3.util.ssl_ import create_urllib3_context
>>> create_urllib3_context()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/requests/packages/urllib3/util/ssl_.py", line 268, in create_urllib3_context
    context.options |= options
  File "/usr/local/lib/python3.6/ssl.py", line 459, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/usr/local/lib/python3.6/ssl.py", line 459, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/usr/local/lib/python3.6/ssl.py", line 459, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  [Previous line repeated 329 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
>>>

是的,这是一个 gevent 问题。 我认为 gevent 还不能与 Python 3.6 一起使用。

super() 调用看起来很奇怪,但它是正确的。 这是获取父类的属性描述符的通用方法。 更改子类中的属性是必要的。 向 Google 询问“David Beazley subclass property”,它会显示相同的内容, https://www.safaribooksonline.com/library/view/python-cookbook-3rd/9781449357337/ch08s08.html

>>> from ssl import SSLContext
>>> super(SSLContext, SSLContext).options
<attribute 'options' of '_ssl._SSLContext' objects>
>>> import _ssl
>>> super(SSLContext, SSLContext).options is _ssl._SSLContext.options
True

调用super(SSLContext, SSLContext).options.__set__(self, value)与在父类的实例上设置选项相同。

这是对同一问题的 gevent 票证的参考:https://github.com/gevent/gevent/issues/903
默认情况下,Gevent 现在已达到 >1.2。 如果您仍然遇到此问题,可以使用简单的pip install --upgrade gevent修复它。

@pirate不能为我解决问题。 还有其他想法吗? 另一个线程被锁定。

@AeroNotix请不要使用这个问题或这个项目的跟踪器来讨论 gevent 问题。

@pirate你能解锁

不, @AeroNotix ,我不是这两个项目的贡献者,也许您可​​以直接通过电子邮件/ irc 向另一个线程中的一个人发送电子邮件?

@pirata这个问题仍然存在于python 3.6.1gevent 1.2.1requests 2.13.0 。 重现步骤:

import requests
import gevent.monkey
gevent.monkey.patch_ssl()
requests.get("https://google.com")

如果我在补丁后导入requests ,一切正常。 过去的情况是无关紧要,我想知道是否可以更改某些内容以保持旧行为。 你怎么看@Lukasa

Requests 在 gevent 和猴子补丁方面存在一些问题,因为它在导入时对 select 模块执行特征检测。 未来的版本将使用更新的 urllib3 更新它,其中包含针对此问题的修复程序,但同时应在导入请求之前应用 gevent 的猴子补丁。

@Lukasa你指的是这个版本吗?

此页面是否有帮助?
0 / 5 - 0 等级