对于我的项目,我必须检查网站的状态(在共享主机上)。
我使用Python请求库。
def getStatusCode(url):
try:
return requests.head(url,timeout=0.3).status_code
except:
return -1
此代码在带有Python3.4的MacOS 10.10下运行良好,其中包含http://www.google.com等网址。如果我拔掉我的ISP电缆,我立即得到了例外。
在带有Python3.4的Ubuntu Server 14.04下,如果我拔掉我的ISP电缆,我永远不会收到超时错误。 Raspbian也有同样的问题。
经过一些测试后,如果我用IP http://216.58.212.100替换网址,Ubuntu Server会引发异常,但我正在共享网络托管上,所以我无法使用IP 。
经过一些研究后,我发现请求库中的超时与DNS查找之间的差异不是由操作系统执行,而是由操作系统执行。
所以我的问题是解决这个问题最美妙的方法是什么?我是否需要在Python中添加额外的超时异常,如:Timeout on a function call
谢谢
答案 0 :(得分:1)
根据查理的鼓励,我在这里发布我的两个解决方案
对于第一个,我在请求标头中添加了主机,因此我可以将IP地址作为url和avoir DNS查找。
def getStatusCode(url):
headers = {'host': 'www.example.com'}
try:
return requests.head(url,timeout=0.3,headers=headers).status_code
except:
return -1
print(getStatusCode('http://1.2.3.4'))
第二种解决方案基于信号的使用,但分辨率为1秒。
class timeout:
def __init__(self, seconds=1, error_message='Timeout'):
self.seconds = seconds
self.error_message = error_message
def handle_timeout(self, signum, frame):
raise TimeoutError(self.error_message)
def __enter__(self):
signal.signal(signal.SIGALRM, self.handle_timeout)
signal.alarm(self.seconds)
def __exit__(self, type, value, traceback):
signal.alarm(0)
def getStatusCode(url):
try:
return requests.head(url,timeout=0.3).status_code
except:
return -1
with timeout(seconds=1):
print(getStatusCode('http://www.example.com'))
(此解决方案来自Thomas Ahle,https://stackoverflow.com/a/22348885/3896729)
答案 1 :(得分:0)
现在我对您的问题有了更好的理解 - 我认为有一种更好的方法是使用您的操作系统ping应用程序,这在Python中并不难做到 - for example。您还应该平均1000个请求并查看平均值,标准偏差,异常值等。原因是如果一个请求需要500毫秒而您想要1毫秒的分辨率,则需要产生至少500个请求来获取任何内容接近你想要的分辨率。
使用Pythons urllib(2)的问题在于它的执行效果几乎不如系统级调用,所以你很难产生足够的线程来获得你想要的时序分辨率。
最后,我会再次检查您的结果商业产品,以确保您的结果相似。例如(没有隶属关系): http://www.thinkbroadband.com/ping