Как скачать файл по http с авторизацией в python 3.0, обходя ошибки?
у меня есть скрипт, который я хотел бы продолжить использовать, но похоже, что мне нужно либо найти обходной путь для ошибки в Python 3, либо понизить до 2.6, и, таким образом, понизить другие скрипты...
надеюсь, кому-то здесь уже удалось найти обходной путь.
проблема в том, что из-за новых изменений в Python 3.0 в отношении байтов и строк не весь код библиотеки, по-видимому, протестирован.
у меня есть скрипт, который downloades страницу с веб-сервера. Этот скрипт передал имя пользователя и пароль как часть url-адреса в python 2.6, но в Python 3.0 это больше не работает.
например, так:
import urllib.request;
url = "http://username:password@server/file";
urllib.request.urlretrieve(url, "temp.dat");
не удается с этим исключением:
Traceback (most recent call last):
File "C:Temptest.py", line 5, in <module>
urllib.request.urlretrieve(url, "test.html");
File "C:Python30liburllibrequest.py", line 134, in urlretrieve
return _urlopener.retrieve(url, filename, reporthook, data)
File "C:Python30liburllibrequest.py", line 1476, in retrieve
fp = self.open(url, data)
File "C:Python30liburllibrequest.py", line 1444, in open
return getattr(self, name)(url)
File "C:Python30liburllibrequest.py", line 1618, in open_http
return self._open_generic_http(http.client.HTTPConnection, url, data)
File "C:Python30liburllibrequest.py", line 1576, in _open_generic_http
auth = base64.b64encode(user_passwd).strip()
File "C:Python30libbase64.py", line 56, in b64encode
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
TypeError: expected bytes, not str
по-видимому, base64-encoding теперь нуждается в байтах и выводит строку, и, таким образом, urlretrieve (или некоторый код в нем), который создает строку username: password и пытается base64-кодировать это для простой авторизации, неудачи.
если я вместо этого попытаюсь использовать urlopen, например:
import urllib.request;
url = "http://username:password@server/file";
f = urllib.request.urlopen(url);
contents = f.read();
потом он выдает это исключение:
Traceback (most recent call last):
File "C:Temptest.py", line 5, in <module>
f = urllib.request.urlopen(url);
File "C:Python30liburllibrequest.py", line 122, in urlopen
return _opener.open(url, data, timeout)
File "C:Python30liburllibrequest.py", line 359, in open
response = self._open(req, data)
File "C:Python30liburllibrequest.py", line 377, in _open
'_open', req)
File "C:Python30liburllibrequest.py", line 337, in _call_chain
result = func(*args)
File "C:Python30liburllibrequest.py", line 1082, in http_open
return self.do_open(http.client.HTTPConnection, req)
File "C:Python30liburllibrequest.py", line 1051, in do_open
h = http_class(host, timeout=req.timeout) # will parse host:port
File "C:Python30libhttpclient.py", line 620, in __init__
self._set_hostport(host, port)
File "C:Python30libhttpclient.py", line 632, in _set_hostport
raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
http.client.InvalidURL: nonnumeric port: 'password@server'
по-видимому, синтаксический анализ url в этой "библиотеке извлечения url следующего поколения" не знает, что делать с именем пользователя и паролями в url.
какие еще варианты у меня есть?
2 ответов
прямо из документов Py3k:http://docs.python.org/dev/py3k/library/urllib.request.html#examples
import urllib.request
# Create an OpenerDirector with support for Basic HTTP Authentication...
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm='PDQ Application',
uri='https://mahler:8092/site-updates.py',
user='klem',
passwd='kadidd!ehopper')
opener = urllib.request.build_opener(auth_handler)
# ...and install it globally so it can be used with urlopen.
urllib.request.install_opener(opener)
urllib.request.urlopen('http://www.example.com/login.html')
мой совет будет поддерживать ваше 2.* филиал в качестве производственной отрасли, пока вы не сможете отсортировать материал 3.0.
Я собираюсь подождать некоторое время, прежде чем перейти к Python 3.0. Кажется, много людей спешат, но я просто хочу, чтобы все было улажено, и приличный выбор сторонних библиотек. Это может занять год, может занять 18 месяцев, но давление на "обновление" для меня действительно низкое.