首页 > 解决方案 > Ubuntu 18.04 中 urllib.request.urlopen 的奇怪行为

问题描述

我一直在使用 Coursera 上 Python 的在线课程(这不是家庭作业),并且在某些 url 的 urllib.request.urlopen 上遇到了问题。对于硬编码到下面代码中的 url,命令 urllib.request.urlopen(serviceurl, context=ctx).read().decode() 超时。如果使用了另一个 url……说http://www.woot.com使用了数据返回。

我已经在我所在位置的两台单独的 Ubuntu 机器上尝试过这个,它们都运行 18.04(默认为 3.6.7)和通过 Anaconda 运行的 3.7.3。我什至重新安装了 Ubuntu,结果相同。

奇怪的是,如果我包含一个超时参数(例如,urllib.request.urlopen(serviceurl, timeout=1, context=ctx).read().decode()),则会返回数据。

此外,该程序在运行 3.6.4 的 macbook air 上成功运行(不管 url),没有超时参数

import urllib.request
import ssl


# Ignore SSL certificate errors
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

address = input('Enter Locaton: ')
if len(address) < 1:
    serviceurl = 'http://py4e-data.dr-chuck.net/comments_42.xml?'
else:
    serviceurl = address

s = urllib.request.urlopen(serviceurl, context=ctx).read().decode()
print(s)

我似乎是唯一一个有这个问题的人,这让我很难过。我刚刚开始熟悉python(C、C#、Java比较熟悉)。任何想法,将不胜感激。

标签: python-3.xurllib

解决方案


回答(我认为)我自己的问题。看起来该网站不喜欢 IP6 套接字。能够将挂起追溯到 socket.py。创建连接中使用的第一个地址是一个不返回任何内容的 IP6 地址和端口。添加超时导致代码从列表中选择下一个地址和端口,即 IP4 并且有效。目前我在 Ubuntu 18.04 中禁用了 IP6 以强制使用 IP4。


推荐阅读