Функция python3 urllib.request.urlopen не работает в Ubuntu 16.04, но работает на 9 других ОС - PullRequest
0 голосов
/ 02 июня 2019

У меня есть небольшая функция 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, скомпилировав его.Спасибо за любую помощь.
...