バグの回避策、Python 3.0で承認してHTTP経由でファイルをダウンロードするには?
-
23-08-2019 - |
質問
私は引き続き使用したいスクリプトを持っていますが、私はどちらかは、Python 3のバグのためのいくつかの回避策を見つける、または2.6にダウングレードする必要があるため、同様に他のスクリプトをダウングレードしたように見えます。 ..
うまくいけば、ここで誰かが既に回避策を見つけるために管理している。
問題は、バイトと文字列についてはPython 3.0で新たな変更ではなく、すべてのライブラリコードに明らかにテストされていることである。
私は、Webサーバーからページをdownloadesスクリプトを持っています。このスクリプトは、Python 2.6でURLの一部としてユーザ名とパスワードを渡されたが、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:\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
明らかに、base64で符号化は、現在のバイトを必要とし、文字列を出力し、従ってurlretrieve(又はその中のいくつかのコード)、ユーザ名の文字列を構築:パスワードを、この単純な承認のためにbase64で符号化しようとするが、失敗します<。 / P>
私の代わりにこのように、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:\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'
どうやら、この「次の世代のURL検索ライブラリ」で解析するURLは、URLにユーザ名とパスワードで何をすべきかを知りません。
私は他にどのような選択肢がありますか?
解決
Py3kのドキュメントから直接:ます。http://ドキュメント。 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')
他のヒント
私のアドバイスは、あなたがソートされた3.0のものを得ることができるまで、本番ブランチとしてあなた2. *ブランチを維持するだろう。
私は、Python 3.0に上を移動する前に、しばらく待つつもりです。そこ多くの人が急いでいるようだが、私はちょうどすべてが整理、およびサードパーティのライブラリのまともな選択します。これは、今年かかる場合があり、それは18ヶ月かかるかもしれないが、「アップグレード」する圧力が私のために本当に低いです。