Come scaricare un file su HTTP con l'autorizzazione in Python 3.0, lavorando alla risoluzione degli errori?

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

  •  23-08-2019
  •  | 
  •  

Domanda

Ho uno script che mi piacerebbe continuare a utilizzare, ma sembra che io sia devo trovare qualche soluzione per un bug in Python 3, o downgrade di nuovo a 2.6, e avendo così a declassare altri script pure. ..

Speriamo che qualcuno qui sono già riusciti a trovare una soluzione alternativa.

Il problema è che a causa dei nuovi cambiamenti in Python 3.0 in materia di byte e stringhe, non tutto il codice della libreria è apparentemente testato.

Ho uno script che scaricabile anche una pagina da un server web. Questo script passò un nome utente e password come parte dell'URL in Python 2.6, ma in Python 3.0, questo non funziona più.

Per esempio, questo:

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

non riesce con questa eccezione:

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

Apparentemente, base64 codifica deve ora byte e genera una stringa, e quindi urlretrieve (o qualche codice in esso) che costruisce una stringa di nome utente: password e cerca di base64 codificare questo per semplice autorizzazione, esito negativo <. / p>

Se io invece cerco di usare urlopen, in questo modo:

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

Poi non riesce con questa eccezione:

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'

A quanto pare l'analisi degli URL in questa "prossima libreria url recupero gen" non sa cosa fare con username e password nel URL.

Quali altre scelte ho?

È stato utile?

Soluzione

Direttamente dalla documentazione 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')

Altri suggerimenti

Il mio consiglio sarebbe quello di mantenere il vostro 2. * ramo come ramo di produzione fino a quando si può ottenere la roba 3.0 allineati.

Ho intenzione di aspettare un po 'prima di passare a Python 3.0. Ci sembra un sacco di gente in fretta, ma voglio solo tutto risolto, e una buona selezione di librerie di terze parti. Questo può richiedere un anno, potrebbero essere necessari 18 mesi, ma la pressione di "upgrade" è davvero basso per me.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top