Estou usando o Python 3.7.3 para executar uma solicitação GET para um arquivo PHP hospedado em meu site. No entanto, quando o executo, recebo o erro abaixo. Eu instalei requests
através pip3
do Homebrew. Estou usando macOS Mojave.
Traceback (última chamada mais recente):
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", linha 600, em urlopen chunked=chunked)
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", linha 343, em _make_request self._validate_conn(conn)
Arquivo "/Library/Frameworks/Python .framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", linha 839, em _validate_conn conn.connect()
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib /python3.7/site-packages/urllib3/connection.py", linha 344, em conectar ssl_context=context)
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/ssl_.py", linha 344, em ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", linha 412, in wrap_socket session=session
File "/Library/Frameworks/Python.framework/Versions/3.7/lib /python3.7/ssl.py", linha 853, em _create self.do_handshake()
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", linha 1117, em do_handshake self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] falha na verificação do certificado: não foi possível obter o certificado do emissor local (_ssl.c:1056)Durante o tratamento da exceção acima, outra exceção ocorreu:
Traceback (última chamada mais recente):
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", linha 449, em send timeout=timeout
Arquivo " /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", linha 638, em urlopen _stacktrace=sys.exc_info()[2])
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/retry.py", linha 398, em incrementos raise MaxRetryError(_pool, url, error ou ResponseError( cause)) urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='ijetlab.com', port=443): Máximo de tentativas excedido com url: /api/api.php?one=1&two=2 (causado por SSLError(SSLCertVerificationError(1 , '[SSL: CERTIFICATE_VERIFY_FAILED] falha na verificação do certificado: não foi possível obter o certificado do emissor local (_ssl.c:1056)')))Durante o tratamento da exceção acima, outra exceção ocorreu:
Traceback (última chamada mais recente):
Arquivo "/Users/maxwellnewberry/Documents/test.py", linha 12, in r = requests.get(url = URL, params = PARAMS)
Arquivo "/Library/Frameworks/Python.framework /Versions/3.7/lib/python3.7/site-packages/requests/api.py", linha 75, in get return request('get', url, params=params, **kwargs)
File "/Library/Frameworks /Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/api.py", linha 60, na solicitação return session.request(method=method, url=url, **kwargs)
Arquivo " /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", linha 533, na solicitação resp = self.send(prep, **send_kwargs)
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", linha 646, em send r = adapter.send(request, **kwargs)
Arquivo "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", linha 514, em send raise SSLError(e, request=request) requests.exceptions.SSLError : HTTPSConnectionPool(host='ijetlab.com', port=443): Máximo de tentativas excedido com url: /api/api.php?one=1&two=2 (Causado por SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificado falha na verificação: não foi possível obter o certificado do emissor local (_ssl.c:1056)')))
Aqui está o código:
# importing the requests library
import requests
# api-endpoint
URL = "https://ijetlab.com/api/api.php"
# defining a params dict for the parameters to be sent to the API
PARAMS = {'one':1, 'two':2}
# sending get request and saving the response as response object
r = requests.get(url = URL, params = PARAMS)
# extracting data in json format
data = r.json()
print(data['response'])
Todas as pesquisas me disseram para executar 'Install Certificates.command', e eu executei – cerca de 100 vezes. Também fiz os certificados de instalação do cliente.
TL;DR
O site remoto parece ser o problema, não o Python. Provavelmente não há correção para isso além de corrigir o site.
Explicação mais longa
O site/servidor com o qual você está lidando aparentemente está configurado incorretamente. Isso não tem nada a ver diretamente com o Python. Dito isso, você pode ignorar quaisquer erros de certificado com, por exemplo:
ou você pode tentar apontar o Python para os certificados ausentes (como apontado por @dave_thompson_085 nos comentários).
No entanto, é improvável que isso seja bom, pois o servidor aparentemente responde com um
500: Internal Server Error
(verificado comcurl
) e umContent-Length: 0
, o que parece indicar um erro no processamento deapi.php
si mesmo (ou seja, não há JSON para processar de qualquer maneira).Se você estiver trabalhando em um ambiente corporativo que descriptografa seu tráfego, ou possivelmente servidores proxy como parte de uma VPN, descobri que a
certifi
biblioteca não inclui o certificado para o servidor de descriptografia no pacote de certificados. Isso deixa você com apenas 1 solução boa, 1 solução medíocre e 1 solução ruim. A má solução é não verificar os certificados. A solução medíocre é pedir ao seu departamento de TI para colocar na lista de permissões o site que você está tentando entrar em contato, mas você terá que pedir repetidamente para cada novo site que tentar entrar em contato.Há um artigo muito bom sobre esse assunto de David Tippet no link a seguir. https://levelup.gitconnected.com/fixing-your-ssl-verify-errors-in-python-71c2201db4b2
Então, qual é a boa solução? Você terá que começar encontrando alguém em seu departamento de TI que possa fornecer a URL ou o endereço IP do seu servidor de descriptografia SSL, ou você pode pedir a eles que forneçam o arquivo .pem em um formato base64 para o servidor. Este é um arquivo de texto claro legível por humanos e se parece com isto:
Exemplo de certificado
Ele terá 7 linhas começando com um comentário
#
, uma linha que diz-----BEGIN CERTIFICATE-----
e uma linha que termina como-----END CERTIFICATE-----
.Abra seu ambiente python e verifique se você tem
certifi
com o comando:import certifi
Em seguida, descubra onde está a cadeia de certificados em seu computador que o Python está usando com
certifi.where()
Navegue até o caminho do arquivo retornado por
certifi.where()
e faça uma cópia desse arquivo caso quebre algo. O meu estava localizado aqui:'C:\Users\user_name\Anaconda3\envs\gispy\lib\site-packages\certifi\cacert.pem'
Abra esse arquivo .txt e copie e cole todo o certificado para seu servidor proxy/descriptografia no final do
cacert.pem
arquivo. Agora suarequests
chamada deve funcionar.Não acho que o servidor seja necessariamente o problema. Estou fazendo algo semelhante, mas minhas duas primeiras linhas são as seguintes.
importar pandas como pd
BCD = pd.read_csv(' https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer/breast-cancer.data ')
Estou fazendo isso simultaneamente no MacBook Pro com Mojave 10.14.6 e em um Microsoft Surface com Windows 10 Enterprise, 10.0.17134, ambos usando Jupyter. Minha instalação do Python é 3.7.3 em ambos.
Ambos estão acessando a Internet pelo mesmo Wi-Fi doméstico.
O Surface pegou na primeira tentativa. O MacBook me dá o mesmo erro que o OP.
Portanto, não é provável que o servidor do banco de dados UCI seja o problema.
No nosso caso, o problema estava relacionado a certificados SSL assinados pelos próprios certificados CA Root & Intermediate. A solução foi - depois de descobrir a localização do arquivo cacert.pem do certifi (import certifi; certifi.where()) - foi anexar o próprio CA Root & Intermediates ao arquivo cacert.pem. Claro, esses próprios certificados estavam no formato PEM.