Если вы запустите
import urllib2
url = 'https://www.5giay.vn/'
urllib2.urlopen(url, timeout=1.0)
подождите несколько секунд, а затем используйте C-c, чтобы прервать программу, вы увидите
File "/usr/lib/python2.7/ssl.py", line 260, in read
return self._sslobj.read(len)
KeyboardInterrupt
Это показывает, что программа зависла на self._sslobj.read(len)
.
Время ожидания SSL увеличивается на socket.timeout
.
Вы можете управлять задержкой до того, как socket.timeout будет поднят, вызвав socket.setdefaulttimeout(1.0)
.
Например,
import urllib2
import socket
socket.setdefaulttimeout(1.0)
url = 'https://www.5giay.vn/'
try:
urllib2.urlopen(url, timeout=1.0)
except IOError as err:
print('timeout')
% time script.py
timeout
real 0m3.629s
user 0m0.020s
sys 0m0.024s
Обратите внимание, что модуль запросов работает успешно, хотя urllib2
нет:
import requests
r = requests.get('https://www.5giay.vn/')
Как установить тайм-аут для всего вызова функции:
socket.setdefaulttimeout
влияет только на то, как долго Python ожидает, прежде чем возникнет исключение, если сервер не выдал ответа.
Ни он, ни urlopen(..., timeout=...)
не устанавливают ограничения по времени для всего вызова функции.
Для этого вы можете использовать события, как показано здесь.
Если вы не хотите устанавливать eventlets
, вы можете использовать multiprocessing
из стандартной библиотеки; хотя это решение не будет масштабироваться так же хорошо, как асинхронное решение, такое как eventlets
.
import urllib2
import socket
import multiprocessing as mp
def timeout(t, cmd, *args, **kwds):
pool = mp.Pool(processes=1)
result = pool.apply_async(cmd, args=args, kwds=kwds)
try:
retval = result.get(timeout=t)
except mp.TimeoutError as err:
pool.terminate()
pool.join()
raise
else:
return retval
def open(url):
response = urllib2.urlopen(url)
print(response)
url = 'https://www.5giay.vn/'
try:
timeout(5, open, url)
except mp.TimeoutError as err:
print('timeout')
Выполнение этого либо завершится успешно, либо истечет время ожидания примерно через 5 секунд настенных часов.
06.12.2014