以下两行代码会一直挂起:
import urllib2
urllib2.urlopen('https://www.5giay.vn/', timeout=5)
我使用的是Python2.7,没有设置http_proxy或其他环境变量。其他网站都可以正常访问。我也可以使用wget下载该网站而没有任何问题。可能出现了什么问题?
import urllib2
urllib2.urlopen('https://www.5giay.vn/', timeout=5)
我使用的是Python2.7,没有设置http_proxy或其他环境变量。其他网站都可以正常访问。我也可以使用wget下载该网站而没有任何问题。可能出现了什么问题?
如果您运行
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)
上。
您可以通过调用socket.setdefaulttimeout(1.0)
来控制引发socket.timeout异常之前的延迟时间。
例如,
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
失败了,但requests 模块 在这里成功了。import requests
r = requests.get('https://www.5giay.vn/')
如何对整个函数调用设置超时:
socket.setdefaulttimeout
只会在服务器未响应时,等待 Python 抛出异常前的时间受到影响。
它和 urlopen(..., timeout=...)
都不能对整个函数调用强制执行时间限制。
要做到这一点,您可以使用 eventlets,如此展示。
如果您不想安装 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秒钟的墙钟时间内成功或超时。