2008-12-27 33 views
7

我有一个脚本,我想继续使用,但它看起来像我要么找到一些解决方案,在Python 3中的错误,或降级到2.6,从而不得不降级其他脚本以及..如何使用python 3.0的授权通过http下载文件,解决错误?

希望这里有人已经设法找到解决方法。

问题是,由于Python 3.0中有关字节和字符串的新更改,并非所有库代码都显然经过测试。

我有一个脚本,可以从网页服务器下载页面。这个脚本在Python 2.6中传递了一个用户名和密码作为url的一部分,但是在Python 3.0中,这不再起作用。

例如,该:

import urllib.request; 
url = "http://username:[email protected]/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编码,失败。

如果我不是尝试使用的urlopen,像这样:

import urllib.request; 
url = "http://username:[email protected]/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: '[email protected]' 

显然,网址在这个“下一代URL检索库”解析没有按不知道如何处理网址中的用户名和密码。

我还有其他选择吗?

回答

20

直接从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') 
+0

您是不是要发表该密码?如果没有,那么我建议删除答案并在那里发布一个新的虚拟数据。感谢您的答案,但看起来很有希望。 – 2008-12-27 23:11:23

0

我的建议是保持你的2 *分公司作为生产分公司,直到你可以得到3.0的东西排序。

我将等待一段时间,然后再转到Python 3.0。似乎很多人都在急于求成,但我只希望所有的东西都能被整理出来,并且还有一些体面的第三方库。这可能需要一年的时间,可能需要18个月,但对于“升级”的压力对我来说真的很低。

相关问题