在requests里,可以通过timeout参数 设置请求超时时间,超时则抛出异常
requests.get(url=url,timeout=(10,30))
timeout=(10,30)表示connect timeout 10秒,read timeout 30秒。
有时候,即使这样设置依然会出现超时永久卡住的情况,仔细搜索资料,发现timeout只是针对connect和read超时,而如果在connect之前就卡住,则会一直卡住,比如从dns服务器获取域名解析ip,这一步卡住的话,程序就一直卡住了,没人管的话卡一个月都行。
我有一个爬虫就是这样,放在国内完全没问题,放在国外服务器就经常requests卡住。全部都加了timeout参数,改善很多,但是还是会偶尔卡住,后来发现是获取dns这一步卡住了。
(验证:urllib 直接使用 socket.getaddrinfo 获取 DNS,写一个循环重复 1000 次,然后你发现自己的程序卡死了那么你应该遇到了和我一样的状况。)
requests的文档有这样描述:
timeout is not a time limit on the entire response download; rather, an exception is raised if the server has not issued a response for timeout seconds (more precisely, if no bytes have been received on the underlying socket for timeout seconds). If no timeout is specified explicitly, requests do not time out.
解决办法
在程序main函数开头用setdefaulttimeout 设置默认请求超时时间。
socket.setdefaulttimeout(timeout)
Set the default timeout in seconds (float) for new socket objects. A value of None indicates that new socket objects have no timeout. When the socket module is first imported, the default is None.
import socket
socket.setdefaulttimeout(30)
设置HTTP或socket超时,来防止请求时间过长,导致程序卡置不前。
上面代码把全局默认dns解析、connect、read 的timeout都设为了30秒。
requests的timeout参数会覆盖默认的connect、read时间,不影响其他请求。
网友评论