似乎我无法考虑urllib2
超时。
我确实读了——我想——所有与这个主题相关的帖子,看来我没有做错什么。我说的对吗?
非常感谢你的帮助。在
场景:
在继续脚本的其余部分之前,我需要检查Internet连接。 然后我编写了一个函数(Net_Access),如下所示。在
一些信息:
cat /proc/sys/kernel/osrelease: 2.6.32-42-generic
我的代码:
#!/usr/bin/env python
import socket
import urllib2
myhost = 'http://www.google.com'
timeout = 3
socket.setdefaulttimeout(timeout)
req = urllib2.Request(myhost)
try:
handle = urllib2.urlopen(req, timeout = timeout)
except urllib2.URLError as e:
socket.setdefaulttimeout(None)
print ('[--- Net_Access() --- No network access')
else:
print ('[--- Net_Access() --- Internet Access OK')
1)工作,LAN连接器插入
^{pr2}$2)超时不工作,LAN连接器拔出
$ time ./Net_Access
[--- Net_Access() --- No network access
real 1m20.235s
user 0m0.048s
sys 0m0.060s
添加到原始post:test results(使用IP而不是FQDN)
正如@unutbu(见注释)所建议的那样,用一个IP地址替换myhost中的FQDN可以解决问题:超时生效。在
LAN连接器已插入…
$time/网络访问
[---Net_Access()---互联网接入正常
real 0m0.289s
user 0m0.036s
sys 0m0.040s
LAN连接器拔出…
$time/网络访问
[---Net_Access()---无网络访问
real 0m3.082s
user 0m0.052s
sys 0m0.024s
这很好,但这意味着超时只能用于IP而不能用于FQDN。奇怪的。。。在
是否有人找到了一种方法来使用urllib2超时而不进入pre-DNS解析并将IP传递给函数,还是您首先使用socket测试连接,然后在确定可以到达目标时激发urllib2?在
非常感谢。在
或许可以试试这个:
当我拔掉网络适配器的插头时,它几乎立即输出False,而在正常情况下,它会输出True。在
我不知道为什么与您的原始代码相比,它的工作速度如此之快(甚至不需要设置timeout参数),但也许它也适用于您。在
今天早上我做了一个实验,结果导致
get_header
不能立即返回。我在路由器关闭的情况下启动了计算机。然后路由器被打开了。然后通过Ubuntu GUI启用了网络和无线。无法建立工作连接。在此阶段,get_header
无法立即返回。在因此,这里有一个更重的解决方案,它在使用
multiprocessing.Pool
的子进程中调用get_header
。pool.apply_async
返回的对象有一个带超时参数的get
方法。如果在timeout
指定的持续时间内没有从get_header
返回结果,则子进程将终止。在因此,
^{pr2}$check_http
在任何情况下都应该在大约1秒内返回结果。在如果您的问题是DNS查找在没有网络连接的情况下要花很长时间(或太长时间)超时,那么是的,这是一个已知的问题,您在
urllib2
本身内无法解决该问题。在那么,所有的希望都破灭了吗?嗯,不一定。在
首先,让我们看看发生了什么。最终,} 将遵从^{} 来创建连接,后者调用^{} 上的} 上的
urlopen
依赖于getaddrinfo
,它(以及它的亲属,如gethostbyname
)是著名的套接字API中的一个关键部分,不能异步运行或中断(在某些平台上,它甚至不是线程安全的)。如果您想自己跟踪源代码,^{create_connection
,后者调用^{socket_getaddrinfo
,后者最终调用真正的getaddrinfo
函数。这是一个臭名昭著的问题,它影响着世界上每种语言编写的每个网络客户端或服务器,而且没有一个好的、简单的解决方案。在一个选择是使用一个已经解决了这个问题的不同的高级库。我相信^{} 依赖于^{} ,这最终也有相同的问题,但是^{} 依赖于{a8},如果使用{a9}构建,它将异步执行名称查找,因此可以超时。在
当然,也可以使用}或其他异步网络库。但是显然,重写所有代码以使用}并不是很简单。在
twisted
或{twisted
HTTP客户机而不是{另一个选择是通过monkey修补标准库来“修复”
urllib2
。如果你想这样做,有两个步骤。在首先,必须提供一个可超时的
getaddrinfo
。您可以通过绑定c-ares
,或者使用ctypes
来访问特定于平台的api,比如linux的getaddrinfo_a
,甚至可以查找命名服务器并直接与它们通信。但真正简单的方法是使用线程。如果你做了很多这样的事情,你会希望使用一个线程或一个小线程池,但是对于小规模的使用,只需为每个调用分离一个线程。一个非常快速和肮脏(读:坏)的实现是:下一步,你必须得到所有你关心的库来使用这个。根据您希望补丁的普遍性(和危险性),您可以替换}中的代码。在
socket.getaddrinfo
本身,或者只是socket.create_connection
,或者只是httplib
甚至{最后一个选择是在更高的层次上解决这个问题。如果你的网络事件发生在后台线程上,你可以对整个事件抛出一个更高级别的超时,如果花了超过
timeout
秒的时间来判断它是否超时,你知道它已经超时了。在相关问题 更多 >
编程相关推荐