Como baixar um arquivo sobre http com autorização em python 3.0, trabalhando em torno de bugs?

StackOverflow https://stackoverflow.com/questions/395451

  •  23-08-2019
  •  | 
  •  

Pergunta

Eu tenho um script que eu gostaria de continuar usando, mas parece que eu quer ter de encontrar alguma solução para um bug no Python 3, ou rebaixamento de volta para 2,6, e, assim, ter a rebaixar outros scripts também. ..

Espero que alguém aqui já conseguiu encontrar uma solução alternativa.

O problema é que, devido às novas mudanças no Python 3.0 sobre bytes e strings, não todo o código da biblioteca é, aparentemente testado.

Eu tenho um script que downloades uma página de um servidor web. Este script passou um nome de usuário e senha como parte do URL em python 2.6, mas em Python 3.0, isso não funciona mais.

Por exemplo, esta:

import urllib.request;
url = "http://username:password@server/file";
urllib.request.urlretrieve(url, "temp.dat");

falha com essa exceção:

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, base64-Encoding agora precisa de bytes em e gera uma string, e, assim, urlretrieve (ou algum código nele), que acumula uma série de usuário: senha, e tenta base64 codificar isso por simples autorização, falha <. / p>

Se eu em vez de tentar usar urlopen, como este:

import urllib.request;
url = "http://username:password@server/file";
f = urllib.request.urlopen(url);
contents = f.read();

Em seguida, ele falha com uma exceção:

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, a análise de URL neste "next gen url biblioteca recuperação" não sabe o que fazer com nome de usuário e senhas na url.

O que outras opções eu tenho?

Foi útil?

Solução

Direto dos docs 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')

Outras dicas

Meu conselho seria para manter o seu 2. * ramo como seu ramo de produção até que você pode obter o material 3.0 ordenados.

Vou esperar um pouco antes de passar para Python 3.0. Parece um monte de pessoas em uma corrida, mas eu só quero tudo resolvido, e uma selecção decente de bibliotecas de terceiros. Isso pode demorar um ano, pode demorar 18 meses, mas a pressão para "upgrade" é realmente baixo para mim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top