Estou coletando estatísticas em uma lista de sites e usando solicitações para simplificar. Aqui está o meu código:
data=[]
websites=['http://google.com', 'http://bbc.co.uk']
for w in websites:
r= requests.get(w, verify=False)
data.append( (r.url, len(r.content), r.elapsed.total_seconds(), str([(l.status_code, l.url) for l in r.history]), str(r.headers.items()), str(r.cookies.items())) )
Agora, quero requests.get
expirar após 10 segundos para que o loop não fique preso.
Essa pergunta também foi interessante antes, mas nenhuma das respostas é clara. Vou dar uma recompensa por isso para obter uma boa resposta.
Ouvi dizer que talvez não usar solicitações seja uma boa ideia, mas como devo obter as coisas boas que as solicitações oferecem. (os da tupla)
python
timeout
python-requests
Kiarash
fonte
fonte
Respostas:
Que tal usar o eventlet? Se você deseja exceder o tempo limite da solicitação após 10 segundos, mesmo se os dados estiverem sendo recebidos, esse snippet funcionará para você:
fonte
eventlet.monkey_patch()
obrigatório?socket
módulo precisa ser macaco remendado, assim pelo menos você vai precisar de umaeventlet.monkey_patch(socket=True)
requests.get('https://github.com', timeout=5)
Defina o parâmetro timeout :
Contanto que você não defina
stream=True
essa solicitação, orequests.get()
tempo limite da chamada será excedido se a conexão demorar mais de dez segundos ou se o servidor não enviar dados por mais de dez segundos.fonte
ATUALIZAÇÃO: https://requests.readthedocs.io/en/master/user/advanced/#timeouts
Na nova versão do
requests
:Se você especificar um único valor para o tempo limite, assim:
O valor do tempo limite será aplicado aos tempos limite
connect
e aoread
tempo limite. Especifique uma tupla se desejar definir os valores separadamente:Se o servidor remoto estiver muito lento, você pode pedir para as solicitações aguardarem uma resposta eternamente, passando None como um valor de tempo limite e, em seguida, recuperando uma xícara de café.
Minha resposta antiga (provavelmente desatualizada) (postada há muito tempo):
Existem outras maneiras de superar esse problema:
1. Use a
TimeoutSauce
classe internaDe: https://github.com/kennethreitz/requests/issues/1928#issuecomment-35811896
2. Use uma bifurcação de solicitações da kevinburke: https://github.com/kevinburke/requests/tree/connect-timeout
A partir de sua documentação: https://github.com/kevinburke/requests/blob/connect-timeout/docs/user/advanced.rst
O kevinburke solicitou que ele fosse mesclado no projeto de solicitações principais, mas ainda não foi aceito.
fonte
this won't work for you use-case
. Ele quis dizer que não funciona com mp3 stream que é procurado pelo outro cara.timeout = int(seconds)
Desde
requests >= 2.4.0
, você pode usar otimeout
argumento, ou seja:Nota:
fonte
Para criar um tempo limite, você pode usar sinais .
A melhor maneira de resolver esse caso é provavelmente
try-except-finally
bloco.Aqui está um exemplo de código:
Existem algumas advertências para isso:
Mas, está tudo na biblioteca python padrão! Exceto pela importação da função sleep, é apenas uma importação. Se você vai usar timeouts em muitos lugares, você pode facilmente colocar TimeoutException, _timeout e singaling em uma função e apenas chamar isso. Ou você pode criar um decorador e colocá-lo em funções, veja a resposta abaixo.
Você também pode configurá-lo como um "gerenciador de contexto" para poder usá-lo com a
with
instrução:Uma possível desvantagem dessa abordagem do gerenciador de contexto é que você não pode saber se o código realmente expirou ou não.
Fontes e leitura recomendada:
fonte
Tente esta solicitação com tempo limite e tratamento de erros:
fonte
Definir
stream=True
e usarr.iter_content(1024)
. Sim, deeventlet.Timeout
alguma forma, não funciona para mim.A discussão está aqui https://redd.it/80kp1h
fonte
Isso pode ser um exagero, mas a fila de tarefas distribuídas do Celery tem um bom suporte para tempos limite.
Em particular, você pode definir um limite de tempo flexível que apenas gera uma exceção em seu processo (para que você possa limpar) e / ou um limite de tempo difícil que encerra a tarefa quando o limite de tempo é excedido.
Nos bastidores, isso usa a mesma abordagem de sinais como mencionado na sua postagem "antes", mas de uma maneira mais utilizável e gerenciável. E se a lista de sites que você está monitorando for longa, você poderá se beneficiar do seu principal recurso - todos os tipos de maneiras de gerenciar a execução de um grande número de tarefas.
fonte
python-requests
mashttplib
usado por solicitações do Python 2.7). O pacote transmite tudo relacionadotimeout
diretamente ao httplib. Eu acho que nada pode ser corrigido no pedido, porque o processo pode permanecer por muito tempo no httplib.Eu acredito que você pode usar
multiprocessing
e não depender de um pacote de terceiros:O tempo limite passado
kwargs
é o tempo limite para obter qualquer resposta do servidor, o argumentotimeout
é o tempo limite para obter a resposta completa .fonte
timeout = (tempo limite de conexão, tempo limite de leitura de dados) ou fornecer um único argumento (tempo limite = 1)
fonte
este código funcionando para socketError 11004 e 10060 ......
fonte
Apesar da pergunta ser sobre solicitações, acho isso muito fácil de fazer com o pycurl CURLOPT_TIMEOUT ou CURLOPT_TIMEOUT_MS.
Não é necessário rosquear ou sinalizar:
fonte
Caso esteja usando a opção,
stream=True
você pode fazer o seguinte:A solução não precisa de sinais ou multiprocessamento.
fonte
Apenas mais uma solução (obtida em http://docs.python-requests.org/en/master/user/advanced/#streaming-uploads )
Antes do upload, você pode descobrir o tamanho do conteúdo:
Mas tenha cuidado, um remetente pode configurar um valor incorreto no campo de resposta 'comprimento do conteúdo'.
fonte
Se for o caso, crie um thread de watchdog que atrapalhe o estado interno das solicitações após 10 segundos, por exemplo:
Observe que, dependendo das bibliotecas do sistema, talvez você não consiga definir o prazo na resolução do DNS.
fonte
Bem, tentei muitas soluções nesta página e ainda enfrentava instabilidades, interrupções aleatórias, baixo desempenho das conexões.
Agora estou usando o Curl e estou muito feliz com a funcionalidade de "tempo máximo" e com as performances globais, mesmo com uma implementação tão ruim:
Aqui, eu defini um parâmetro de tempo máximo de 6 segundos, englobando o tempo de conexão e transferência.
Tenho certeza que o Curl tem uma boa ligação python, se você preferir manter a sintaxe python :)
fonte
Existe um pacote chamado timeout-decorator que você pode usar para atingir o tempo limite de qualquer função python.
Ele usa a abordagem de sinais sugerida por algumas respostas. Como alternativa, você pode dizer para usar o multiprocessamento em vez de sinais (por exemplo, se você estiver em um ambiente com vários threads).
fonte
Estou usando as solicitações 2.2.1 e o eventlet não funcionou para mim. Em vez disso, consegui usar o tempo limite do gevent, pois o gevent é usado no meu serviço para o gunicorn.
Observe que gevent.timeout.Timeout não é capturado pelo tratamento geral de exceções. Portanto, capture
gevent.timeout.Timeout
ou passe explicitamente uma exceção diferente para ser usada da seguinte maneira:with gevent.Timeout(5, requests.exceptions.Timeout):
embora nenhuma mensagem seja passada quando essa exceção for gerada.fonte
Eu vim com uma solução mais direta que é reconhecidamente feia, mas resolve o problema real. É mais ou menos assim:
Você pode ler a explicação completa aqui
fonte
timeout
parâmetro pararequests.get()
sem soluções alternativas feias 2 embora ambos não irá limitar o tempo limite total de ao contrárioeventlet.Timeout(10)