headers - ¿Cómo descargar un archivo a través de http con autorización en python 3.0, trabajando alrededor de los errores?
urllib.urlencode python 3 (2)
Directo desde los documentos de 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'')
Tengo un script que me gustaría seguir usando, pero parece que tengo que encontrar alguna solución para un error en Python 3, o rebajar de nuevo a 2.6, y tener que degradar otros scripts también ...
Esperemos que alguien aquí ya haya logrado encontrar una solución alternativa.
El problema es que debido a los nuevos cambios en Python 3.0 en cuanto a bytes y cadenas, no todo el código de la biblioteca es aparentemente probado.
Tengo un script que descarga una página de un servidor web. Esta secuencia de comandos pasó un nombre de usuario y una contraseña como parte de la url en Python 2.6, pero en Python 3.0, esto ya no funciona.
Por ejemplo, esto:
import urllib.request;
url = "http://username:password@server/file";
urllib.request.urlretrieve(url, "temp.dat");
falla con esta excepción:
Traceback (most recent call last):
File "C:/Temp/test.py", line 5, in <module>
urllib.request.urlretrieve(url, "test.html");
File "C:/Python30/lib/urllib/request.py", line 134, in urlretrieve
return _urlopener.retrieve(url, filename, reporthook, data)
File "C:/Python30/lib/urllib/request.py", line 1476, in retrieve
fp = self.open(url, data)
File "C:/Python30/lib/urllib/request.py", line 1444, in open
return getattr(self, name)(url)
File "C:/Python30/lib/urllib/request.py", line 1618, in open_http
return self._open_generic_http(http.client.HTTPConnection, url, data)
File "C:/Python30/lib/urllib/request.py", line 1576, in _open_generic_http
auth = base64.b64encode(user_passwd).strip()
File "C:/Python30/lib/base64.py", line 56, in b64encode
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
TypeError: expected bytes, not str
Aparentemente, la codificación de base64 ahora necesita bytes en y produce una cadena, y por lo tanto urlretrieve (o algún código en el mismo) que crea una cadena de nombre de usuario: contraseña, e intenta codificar en base64 para una autorización simple, falla.
Si, en cambio, trato de usar urlopen, así:
import urllib.request;
url = "http://username:password@server/file";
f = urllib.request.urlopen(url);
contents = f.read();
Luego falla con esta excepción:
Traceback (most recent call last):
File "C:/Temp/test.py", line 5, in <module>
f = urllib.request.urlopen(url);
File "C:/Python30/lib/urllib/request.py", line 122, in urlopen
return _opener.open(url, data, timeout)
File "C:/Python30/lib/urllib/request.py", line 359, in open
response = self._open(req, data)
File "C:/Python30/lib/urllib/request.py", line 377, in _open
''_open'', req)
File "C:/Python30/lib/urllib/request.py", line 337, in _call_chain
result = func(*args)
File "C:/Python30/lib/urllib/request.py", line 1082, in http_open
return self.do_open(http.client.HTTPConnection, req)
File "C:/Python30/lib/urllib/request.py", line 1051, in do_open
h = http_class(host, timeout=req.timeout) # will parse host:port
File "C:/Python30/lib/http/client.py", line 620, in __init__
self._set_hostport(host, port)
File "C:/Python30/lib/http/client.py", line 632, in _set_hostport
raise InvalidURL("nonnumeric port: ''%s''" % host[i+1:])
http.client.InvalidURL: nonnumeric port: ''password@server''
Aparentemente, el análisis de la URL en esta "biblioteca de recuperación de url de próxima generación" no sabe qué hacer con el nombre de usuario y las contraseñas en la url.
¿Qué otras opciones tengo?
Mi consejo sería mantener su rama 2. * como su rama de producción hasta que pueda ordenar las 3,0 cosas.
Voy a esperar un tiempo antes de pasar a Python 3.0. Parece que hay mucha gente apurada, pero solo quiero que todo esté resuelto y una buena selección de bibliotecas de terceros. Esto puede tomar un año, puede llevar 18 meses, pero la presión para "actualizar" es realmente baja para mí.