Python urllib.request中的Unicode字符串

Python urllib.request中的Unicode字符串,python,python-3.x,unicode,encoding,Python,Python 3.x,Unicode,Encoding,简短版本:我有一个变量s='bär'。我需要将s转换为ASCII,以便s='b%C3%A4r' 长版本: 我正在使用urllib.request.urlopen()从URL读取mp3发音文件。这很有效,只是我遇到了一个问题,因为URL通常包含unicode字符。例如,德语的“Bär”。完整的URL是https://d7mj4aqfscim2.cloudfront.net/tts/de/token/bär。事实上,在Chrome中输入这个URL是有效的,可以让我毫无问题地找到mp3文件。但是,将相

简短版本:我有一个变量
s='bär'
。我需要将
s
转换为ASCII,以便
s='b%C3%A4r'

长版本:

我正在使用
urllib.request.urlopen()
从URL读取mp3发音文件。这很有效,只是我遇到了一个问题,因为URL通常包含unicode字符。例如,德语的“Bär”。完整的URL是
https://d7mj4aqfscim2.cloudfront.net/tts/de/token/bär
。事实上,在Chrome中输入这个URL是有效的,可以让我毫无问题地找到mp3文件。但是,将相同的URL提供给
urllib
会产生问题

我确定这是一个unicode问题,因为堆栈跟踪读取:

Traceback (most recent call last):
  File "importer.py", line 145, in <module>
    download_file(tuple[1], tuple[0], ".mp3")
  File "importer.py", line 81, in download_file
    with urllib.request.urlopen(url) as in_stream, open(to_fname+ext, 'wb') as out_file: #`with object as name:` safely __enter__() and __exit__() the runtime of object. `as` assigns `name` as referring to the object `object`.
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 162, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 465, in open
    response = self._open(req, data)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 483, in _open
    '_open', req)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 443, in _call_chain
    result = func(*args)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 1283, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py", line 1240, in do_open
    h.request(req.get_method(), req.selector, req.data, headers)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py", line 1083, in request
    self._send_request(method, url, body, headers)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py", line 1118, in _send_request
    self.putrequest(method, url, **skips)
  File "C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py", line 960, in putrequest
    self._output(request.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode character '\xfc' in position 19: ordinal not in range(128)
回溯(最近一次呼叫最后一次):
文件“importer.py”,第145行,在
下载_文件(元组[1],元组[0],“.mp3”)
下载文件中第81行的文件“importer.py”
将urllib.request.urlopen(url)作为in_stream,将(to_fname+ext,'wb')作为out_文件:35; `以对象作为名称:`安全地uuu输入uuuuuuuuuuuuuuuuuuuuuuuuuuuuu()和uuuuuuuuu退出uuuuuuuuuuuuu`as`assigns`name`指的是对象`object`。
urlopen中的文件“C:\Users\quesm\AppData\Local\Programs\Python 35-32\lib\urllib\request.py”,第162行
返回opener.open(url、数据、超时)
文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py”,第465行,打开
响应=自身打开(请求,数据)
文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py”,第483行,打开
"开放",
文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py”,第443行,在调用链中
结果=func(*args)
文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py”,第1283行,https\u打开
上下文=self.\u上下文,检查主机名=self.\u检查主机名)
文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\urllib\request.py”,第1240行,在do\u open中
h、 请求(请求获取方法(),请求选择器,请求数据,标题)
请求中的文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py”,第1083行
self.\u发送请求(方法、url、正文、标题)
文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py”,第1118行,在发送请求中
putrequest(方法、url、**跳过)
文件“C:\Users\quesm\AppData\Local\Programs\Python\Python35-32\lib\http\client.py”,第960行,在putrequest中
self.\u输出(request.encode('ascii'))
UnicodeEncodeError:“ascii”编解码器无法对位置19中的字符“\xfc”进行编码:序号不在范围内(128)
。。。除了明显的
unicodeincoder错误
,我可以看到它正在尝试将
encode()
编码为ASCII

有趣的是,当我从Chrome复制URL(而不是简单地将其输入Python解释器)时,它将
bär
转换为
b%C3%A4r
。当我将其馈送到
urllib.request.urlopen()
时,它处理得很好,因为所有这些字符都是ASCII字符。所以我的目标是在我的程序中进行这种转换。我试图将原始字符串转换为unicode等效字符串,但其所有变体中的
unicodedata.normalize();此外,我不确定如何将Unicode存储为ASCII,因为Python 3将所有字符串存储为Unicode,因此不会尝试转换文本。

使用:



简单地连接字符串和使用
urljoin()
之间有区别吗?另外,这种类型的Unicode有名称吗?考虑到我从
normalize()
获得的Unicode完全不同,我想知道在讨论时如何命名它们。对于您的情况,并不严格要求使用
urljoin
。但是请考虑:<代码> URLLIB .PARSE。http://example.com/a/b/c“,”/x/y/z')
它不是unicode。我听说有人叫它。我试过了,它删除了
/a/b/c
部分。但是将
/x/y/z
更改为
x/y/z
会使生成的url不同,更改为
emaple.com/a/b/x/y/z
。我真的不知道这个URL的哪个部分将被保留/替换。@ AlexG,在一些文档(’)中考虑链接(‘A.html’,‘//地方/html’)。code>urljoin用于获取这些链接的绝对url。
>>> urllib.parse.quote('bär')
'b%C3%A4r'
>>> urllib.parse.urljoin('https://d7mj4aqfscim2.cloudfront.net/tts/de/token/',
...                      urllib.parse.quote('bär'))
'https://d7mj4aqfscim2.cloudfront.net/tts/de/token/b%C3%A4r'