我有一个小的python3函数,可以使用urllib.request.urlopen
或urllib.request.urlretrieve
从Internet下载一些文件。我在基于ubuntu 16.04的docker容器中的更大代码中运行此功能。尝试使用http协议下载文件时,调用失败,错误代码为503 Service Unavailable
。从https服务器下载网页内容时,握手期间呼叫失败。
以下是我从http服务器下载一些tarball的电话:
url = "http://example.com/file.tar.gz"
urllib.request.urlretrieve(url, "file.tar.gz")
以上通话失败,并显示错误
File "/usr/lib/python3.5/urllib/request.py", line 188, in urlretrieve
File "/usr/lib/python3.5/urllib/request.py", line 163, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.5/urllib/request.py", line 472, in open
response = meth(req, response)
File "/usr/lib/python3.5/urllib/request.py", line 582, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python3.5/urllib/request.py", line 510, in error
return self._call_chain(*args)
File "/usr/lib/python3.5/urllib/request.py", line 444, in _call_chain
result = func(*args)
File "/usr/lib/python3.5/urllib/request.py", line 590, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 503: Service Unavailable
以下是我对https的处理方式:
def download_report(self, id, output_file):
ssl_def_function = ssl._create_default_https_context
ssl._create_default_https_context = ssl._create_unverified_context
css = urllib.request.urlopen(self.url + "/print.css")
report = urllib.request.urlopen(self.url + "/run/" + id + "/report/")
with open(output_file, "w+") as f:
# We need to embed the CSS first
css = str(css.read(), "utf-8")
report = str(report.read(), "utf-8").replace("<head>", "<head><style>%s</style>" % css)
f.write(report)
ssl._create_default_https_context = ssl_def_function
,但以下操作失败:
Traceback (most recent call last):
File "/usr/lib/python3.5/urllib/request.py", line 1254, in do_open
h.request(req.get_method(), req.selector, req.data, headers)
File "/usr/lib/python3.5/http/client.py", line 1106, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python3.5/http/client.py", line 1151, in _send_request
self.endheaders(body)
File "/usr/lib/python3.5/http/client.py", line 1102, in endheaders
self._send_output(message_body)
File "/usr/lib/python3.5/http/client.py", line 934, in _send_output
self.send(msg)
File "/usr/lib/python3.5/http/client.py", line 877, in send
self.connect()
File "/usr/lib/python3.5/http/client.py", line 1260, in connect
server_hostname=server_hostname)
File "/usr/lib/python3.5/ssl.py", line 377, in wrap_socket
_context=self)
File "/usr/lib/python3.5/ssl.py", line 752, in __init__
self.do_handshake()
File "/usr/lib/python3.5/ssl.py", line 988, in do_handshake
self._sslobj.do_handshake()
File "/usr/lib/python3.5/ssl.py", line 633, in do_handshake
self._sslobj.do_handshake()
ConnectionResetError: [Errno 104] Connection reset by peer
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/mm/Downloads/pycharm-community-2019.1.3/helpers/pydev/pydevd.py", line 1758, in <module>
main()
File "/home/mm/Downloads/pycharm-community-2019.1.3/helpers/pydev/pydevd.py", line 1752, in main
globals = debugger.run(setup['file'], None, None, is_module)
File "/home/mm/Downloads/pycharm-community-2019.1.3/helpers/pydev/pydevd.py", line 1147, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/home/mm/Downloads/pycharm-community-2019.1.3/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "/tmp/prj/Uploader.py", line 148, in <module>
handler.download_report(id), output_file)
File "/tmp/prj/Helper.py", line 251, in download_report
css = urllib.request.urlopen(self.url + "/print.css")
File "/usr/lib/python3.5/urllib/request.py", line 163, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.5/urllib/request.py", line 466, in open
response = self._open(req, data)
File "/usr/lib/python3.5/urllib/request.py", line 484, in _open
'_open', req)
File "/usr/lib/python3.5/urllib/request.py", line 444, in _call_chain
result = func(*args)
File "/usr/lib/python3.5/urllib/request.py", line 1297, in https_open
context=self._context, check_hostname=self._check_hostname)
File "/usr/lib/python3.5/urllib/request.py", line 1256, in do_open
raise URLError(err)
urllib.error.URLError: <urlopen error [Errno 104] Connection reset by peer>
Process finished with exit code 1
值得一提的是,相同的代码可在以下操作系统(docker容器)上完美运行,但仅在Ubuntu 16.04上失败