Как не блокировать начальное соединение с запросами python?

У меня есть сервер, который использует запросы для выполнения запросов к другому серверу, который может работать или не работать. Если этот сервер не работает, я не хочу блокировать его надолго; Я могу просто сразу обработать ошибку. Однако параметр тайм-аута, по-видимому, не применяется к процессу установления начального соединения.

С терминала запускаю:

>>> import time
>>> import requests
>>> t1 = time.time() ; exec("try: requests.get('http://192.168.99.100/', timeout=1.0)\nexcept: pass") ; t2 = time.time() ; t2 - t1
21.00611114501953

Это занимает около 21 секунды и не зависит от времени ожидания, которое я даю. Я также пытался использовать тайм-аут eventlet, но получилось то же самое:

>>> import time
>>> import eventlet
>>> requests = eventlet.import_patched('requests')
>>> t1 = time.time() ; exec("try: \n  with eventlet.Timeout(1): requests.get('http://192.168.99.100/')\nexcept: pass") ; t2 = time.time() ; t2 - t1
21.00276017189026

Ошибка, которую я получаю для подключения:

ConnectionError: ('Connection aborted.', error(11, 'Resource temporarily unavailable'))

Наконец, я запускаю python в подсистеме Windows для Linux, которая может работать с сокетами по-разному.


person Akh    schedule 28.10.2016    source источник
comment
У меня это работает на OS X. Возможно, это проблема, связанная с Windows. В качестве обходного пути вы можете использовать поток - поэтому, если вызов запроса в потоке не ответил в течение тайм-аута, просто продолжите основной поток.   -  person J. P. Petersen    schedule 28.10.2016
comment
@ J.P.Petersen Я думаю, что это, вероятно, проблема, поскольку WSL все еще находится в разработке.   -  person Akh    schedule 29.10.2016


Ответы (2)


Из документов:

тайм-аут не является ограничением по времени на загрузку всего ответа; скорее, исключение возникает, если сервер не выдал ответ в течение секунд ожидания (точнее, если ни один байт не был получен на базовом сокете в течение секунд ожидания).

При этом пример с использованием чего-то вроде опроса.

import gevent, time
import requests

from gevent import monkey, spawn, sleep
monkey.patch_all() # for working with requests/sockets


do_not_wait = []
print(time.time())

do_not_wait.append(gevent.spawn(requests.get, 'http://192.168.99.100/', timeout=1.0))
do_not_wait.append(gevent.spawn(requests.get, 'http://192.168.99.100/', timeout=1.0))
do_not_wait.append(gevent.spawn(requests.get, 'http://192.168.99.100/', timeout=1.0))

[x.start() for x in do_not_wait]
print(time.time())

while True:
    sleep(1)
    print([x.ready() for x in do_not_wait])
person jmunsch    schedule 28.10.2016

Вы можете использовать диспетчер задач (например, celery), а затем установить время ожидания в рабочем потоке. Я думаю, что requests поддерживает gevent, а не eventlet, поэтому, возможно, вы видите те же проблемы при использовании eventlet.

person notorious.no    schedule 30.10.2016