Python的urllib.request.urlopen与互联网连接中断

时间:2014-07-05 15:40:06

标签: python python-3.x urllib python-3.4

我在使用python的urllib时遇到了一些问题并且中断了互联网连接:在没有活动的互联网连接的情况下,我先无法从urllib.request.urlopen获取信息。 以下工作正常:

 > python
 >>> import urllib.request
 >>> urllib.request.urlopen("http://www.google.com")
 <http.client.HTTPResponse object at 0x7f6f54681438>

 #Now disable internet connection:
 > sudo ip link set enp4s0 down

 >>> urllib.request.urlopen("http://www.google.com")
 Traceback (most recent call last):
   File "/usr/lib/python3.4/urllib/request.py", line 1189, in do_open
     h.request(req.get_method(), req.selector, req.data, headers)
   File "/usr/lib/python3.4/http/client.py", line 1090, in request
     self._send_request(method, url, body, headers)
   File "/usr/lib/python3.4/http/client.py", line 1128, in _send_request
     self.endheaders(body)
   File "/usr/lib/python3.4/http/client.py", line 1086, in endheaders
     self._send_output(message_body)
   File "/usr/lib/python3.4/http/client.py", line 924, in _send_output
     self.send(msg)
   File "/usr/lib/python3.4/http/client.py", line 859, in send
     self.connect()
   File "/usr/lib/python3.4/http/client.py", line 836, in connect
     self.timeout, self.source_address)
   File "/usr/lib/python3.4/socket.py", line 491, in create_connection
     for res in getaddrinfo(host, port, 0, SOCK_STREAM):
   File "/usr/lib/python3.4/socket.py", line 530, in getaddrinfo
     for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
 socket.gaierror: [Errno -2] Name or service not known

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "/usr/lib/python3.4/urllib/request.py", line 153, in urlopen
     return opener.open(url, data, timeout)
   File "/usr/lib/python3.4/urllib/request.py", line 455, in open
     response = self._open(req, data)
   File "/usr/lib/python3.4/urllib/request.py", line 473, in _open
     '_open', req)
   File "/usr/lib/python3.4/urllib/request.py", line 433, in _call_chain
     result = func(*args)
   File "/usr/lib/python3.4/urllib/request.py", line 1215, in http_open
     return self.do_open(http.client.HTTPConnection, req)
   File "/usr/lib/python3.4/urllib/request.py", line 1192, in do_open
     raise URLError(err)
 urllib.error.URLError: <urlopen error [Errno -2] Name or service not known>

 #Reenable internet connection:
 > sudo ip link set enp4s0 up #and wait a bit

 >>> urllib.request.urlopen("http://www.google.com")
 <http.client.HTTPResponse object at 0x7f6f5468c898>

到目前为止一切顺利。现在完全相同的事情,但没有第一次调用urlopen:

 > python
 >>> import urllib.request
 # do not call urlopen before internet is down...


 #Now disable internet connection:
 > sudo ip link set enp4s0 down

 >>> urllib.request.urlopen("http://www.google.com")
 [exactly the same error message as above]

 #Reenable internet connection:
 > sudo ip link set enp4s0 up #and wait a bit

 #Ensure internet connection is up
 > ip link show enp4s0 up
 2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP [...] 


 >>> urllib.request.urlopen("http://www.google.com")
 [exactly the same error message as above]
 #What's the problem? The internet connection IS up

 #However:
 > host www.google.com
 www.google.com has address 173.194.69.104
 [...]
 >>> urllib.request.urlopen("http://173.194.69.104")
 <http.client.HTTPResponse object at 0x7f3116a72e48>

所以我想它必须用DNS(-Caching)做点什么?

最后有关我系统的一些信息:

 > python --version
 Python 3.4.1
 > uname -a
 Linux charon 3.15.3-1-ARCH #1 SMP PREEMPT Tue Jul 1 07:32:45 CEST 2014 x86_64 GNU/Linux

抱歉奇怪的格式化。我将'normal'(前缀为'&gt;')和python(前缀为'&gt;&gt;&gt;')shell命令混为一谈,以使命令序列清晰(显然发生在不同的终端)。

1 个答案:

答案 0 :(得分:2)

您正在使用well-known glibc problem。人们可以争论这是否是对glibc的误用,或者glibc是否在这里做错了。 res_init不是POSIX的一部分,而是源自BSD的接口,因此很难以独立于平台的方式做到正确。

对于此问题,似乎没有针对python的错误报告,因此您可能希望file one

作为一种解决方法,您可以使用ctypes自己拨打res_init,但我不知道该怎么做才能完全摆脱困境。