2008-12-27 3 views
7

Ich habe ein Skript, das ich gerne weiter verwenden würde, aber es sieht so aus, als müsste ich entweder eine Abhilfe für einen Fehler in Python 3 finden oder ein Downgrade auf 2.6 durchführen und somit auch andere Skripte herunterstufen. .Wie kann ich eine Datei über HTTP mit Autorisierung in Python 3.0 herunterladen, um Fehler zu umgehen?

Hoffentlich hat jemand hier schon einen Workaround gefunden.

Das Problem ist, dass aufgrund der neuen Änderungen in Python 3.0 in Bezug auf Bytes und Zeichenfolgen nicht der gesamte Bibliothekscode anscheinend getestet wird.

Ich habe ein Skript, das eine Seite von einem Webserver herunterlädt. Dieses Skript hat einen Benutzernamen und ein Passwort als Teil der URL in Python 2.6 übergeben, aber in Python 3.0 funktioniert das nicht mehr.

Zum Beispiel folgt aus:

import urllib.request; 
url = "http://username:[email protected]/file"; 
urllib.request.urlretrieve(url, "temp.dat"); 

mit dieser Ausnahme fehlschlägt:

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 

Offensichtlich Base64-Kodierung benötigt jetzt Bytes und gibt eine Zeichenfolge, und somit urlretrieve (oder einen Code darin), die eine Zeichenfolge von Benutzername erstellt: Kennwort, und versucht, Base64-encodieren dies für einfache Autorisierung, schlägt fehl.

Wenn ich stattdessen versuchen urlopen zu verwenden, wie folgt aus:

import urllib.request; 
url = "http://username:[email protected]/file"; 
f = urllib.request.urlopen(url); 
contents = f.read(); 

Dann schlägt es mit dieser Ausnahme:

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: '[email protected]' 

offenbar die URL in dieser "Next-Gen-URL abrufen Bibliothek" Parsen doesn Ich weiß nicht, was ich mit Benutzername und Passwörtern in der URL machen soll.

Welche anderen Möglichkeiten habe ich?

Antwort

20

Direkt vom Py3k docs: 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') 
+0

meinst du, dieses Passwort zu posten? Wenn nicht, dann empfehle ich, die Antwort zu löschen und eine neue mit Dummy-Daten zu veröffentlichen. Danke für die Antwort, das sieht vielversprechend aus. –

+3

Direkt aus der Python-Dokumentation: P –

+4

Klem ist wahrscheinlich ziemlich sauer, wenn das sein echtes Passwort ist :) –

0

Mein Rat wäre, um Ihre 2. * Niederlassung als Produktionszweig zu halten, bis die 3,0 Sachen sortiert zu bekommen.

Ich werde eine Weile warten, bevor ich zu Python 3.0 übergehe. Es scheint eine Menge Leute in Eile zu sein, aber ich will nur alles aussortiert haben und eine ordentliche Auswahl an Bibliotheken von Drittanbietern. Dies kann ein Jahr dauern, es kann 18 Monate dauern, aber der Druck auf "upgrade" ist wirklich niedrig für mich.

Verwandte Themen