У меня есть небольшая функция python3, которая загружает некоторые файлы из Интернета, используя urllib.request.urlopen
или urllib.request.urlretrieve
.Я запускаю эту функцию в большем коде в контейнере Docker на основе Ubuntu 16.04.При попытке загрузить файл по протоколу http сбой вызова с кодом ошибки 503 Service Unavailable
.При загрузке содержимого веб-страницы с сервера https вызов не выполняется во время рукопожатия.
Ниже приведен вызов, который я выполняю для загрузки архива с http-сервера:
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
Стоит отметить, что один и тот же код отлично работает в следующих ОС (контейнерах докеров), но не работает только в Ubuntu16.04
- Ubuntu (14.04, 18.04)
- Fedora (27, 28, 29)
- CentOS (7.4, 7.5)
- OpenSuse (42.3, 15.0)
- Windows Я даже установил Ubuntu 16.04 на виртуальной машине, и он также не работает.Я также попытался запустить контейнер на нескольких машинах, и все они перестали работать с одной и той же ошибкой.Это заставило меня задуматься на 2 дня, и я не могу найти решение.Я убедился, что OpenSSL и libssl-dev установлены.Я также попробовал Python 3.7, скомпилировав его.Спасибо за любую помощь.