Ao solicitar um https: // url, o método request
cai em uma recursão infinita.
O problema é este método em python/ssl.py
.
@options.setter
def options(self, value):
super(SSLContext, SSLContext).options.__set__(self, value)
O commit que introduziu esta linha no python é este https://hg.python.org/cpython/rev/c32e9f9b00f7.
O erro real é parecido com este:
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
Testado usando python 3.6.0b4
.
Na verdade, isso parece ser um bug na biblioteca padrão: parece que eles introduziram uma recursão infinita ao definir opções diretamente. @tiran?
Não consigo reproduzir o problema na minha máquina (Python do último branch hg 3.6)
$ ./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
Eu apenas tentei reproduzi-lo do final dos pedidos; Não consigo acertar em 3.6.0b4 ou 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]>
Poderia ser algo específico da plataforma ou URL?
(OS X 10.12.1, 16B2659, de minha parte)
Requests também funciona com Python 3.6.0 da hg:
$ ./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]>
Ok, agora isso parece uma situação "impossível de reproduzir". Pode valer a pena dar uma olhada em sua instalação @juokaz , parece estar se comportando um pouco mal.
Depois de mais depuração, fui capaz de reproduzi-lo como um problema de gevent
(que era o contexto no qual estava usando).
Estou supondo que terei que levá-lo para ajudar as pessoas a darem uma olhada. Obrigado por analisar isso, todos.
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
>>>
Sim, este é um problema gevent. Eu diria que gevent ainda não funciona com Python 3.6.
A chamada super () parece estranha, mas está correta. É a maneira genérica de buscar o descritor de atributo da classe pai. É um mal necessário alterar uma propriedade em uma subclasse. Peça ao Google "propriedade de subclasse de David Beazley" e ela mostrará a mesma, 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
A chamada super(SSLContext, SSLContext).options.__set__(self, value)
é a mesma que definir opções em uma instância da classe pai.
Aqui está a referência ao tíquete gevent para o mesmo problema: https://github.com/gevent/gevent/issues/903
Gevent agora aumentou para> 1,2 por padrão. Se você ainda estiver tendo esse problema, ele pode ser corrigido com um simples pip install --upgrade gevent
.
@pirate, isso não
@AeroNotix, por favor, não use este problema ou o rastreador deste projeto para discutir problemas de gevent.
@pirate você pode desbloquear esse tíquete, então? Ainda estou tendo o mesmo problema no python 3.6 com versões atualizadas de tudo.
Não, @AeroNotix , não sou um contribuidor em nenhum dos projetos, talvez você possa enviar um e-mail / irc para uma das pessoas do outro tópico diretamente?
@pirata Este problema ainda existe com python 3.6.1
, gevent 1.2.1
, requests 2.13.0
. Passos para reproduzir:
import requests
import gevent.monkey
gevent.monkey.patch_ssl()
requests.get("https://google.com")
Se eu importar requests
após o patch, tudo funcionará. Costumava ser o caso em que não importava e estou me perguntando se algo pode ser alterado para manter o antigo comportamento. O que você acha @Lukasa ?
Requests tem alguns problemas com gevent e monkey patching porque executa a detecção de recursos no módulo de seleção no momento da importação. Uma versão futura irá atualizá-lo com um urllib3 mais recente que contém correções para esse problema, mas, enquanto isso, o patch do macaco do gevent deve ser aplicado antes de importar solicitações.
@Lukasa você está se referindo a este lançamento ?
Comentários muito úteis
Requests tem alguns problemas com gevent e monkey patching porque executa a detecção de recursos no módulo de seleção no momento da importação. Uma versão futura irá atualizá-lo com um urllib3 mais recente que contém correções para esse problema, mas, enquanto isso, o patch do macaco do gevent deve ser aplicado antes de importar solicitações.