gpt4 book ai didi

python - urllib.urlencode 不喜欢 unicode 值 : how about this workaround?

转载 作者:IT老高 更新时间:2023-10-28 20:32:56 25 4
gpt4 key购买 nike

如果我有这样的对象:

d = {'a':1, 'en': 'hello'}

...那我可以传给urllib.urlencode,没问题:

percent_escaped = urlencode(d)
print percent_escaped

但如果我尝试传递一个类型为 unicode 的对象,游戏结束:

d2 = {'a':1, 'en': 'hello', 'pt': u'olá'}
percent_escaped = urlencode(d2)
print percent_escaped # This fails with a UnicodeEncodingError

所以我的问题是关于准备传递给 urlencode 的对象的可靠方法。

我想出了这个函数,我只需遍历对象并编码字符串或 unicode 类型的值:

def encode_object(object):
for k,v in object.items():
if type(v) in (str, unicode):
object[k] = v.encode('utf-8')
return object

这似乎有效:

d2 = {'a':1, 'en': 'hello', 'pt': u'olá'}
percent_escaped = urlencode(encode_object(d2))
print percent_escaped

然后输出 a=1&en=hello&pt=%C3%B3la,准备传递给 POST 调用或其他任何东西。

但是我的 encode_object 函数在我看来真的很不稳定。一方面,它不处理嵌套对象。

另一方面,我对 if 语句感到紧张。还有其他我应该考虑的类型吗?

并且正在将某物的 type() 与 native 对象进行比较,就像这种好习惯?

type(v) in (str, unicode) # not so sure about this...

谢谢!

最佳答案

你确实应该紧张。您可能在某些数据结构中混合了字节和文本的整个想法是可怕的。它违反了处理字符串数据的基本原则:在输入时解码,在 unicode 中工作,在输出时编码。

根据评论更新:

您即将输出某种 HTTP 请求。这需要准备为字节字符串。如果您的 dict 中有序数 >= 128 的 unicode 字符,则 urllib.urlencode 无法正确准备该字节字符串这一事实确实很不幸。如果您的 dict 中混合了字节字符串和 unicode 字符串,则需要小心。让我们看看 urlencode() 的作用:

>>> import urllib
>>> tests = ['\x80', '\xe2\x82\xac', 1, '1', u'1', u'\x80', u'\u20ac']
>>> for test in tests:
... print repr(test), repr(urllib.urlencode({'a':test}))
...
'\x80' 'a=%80'
'\xe2\x82\xac' 'a=%E2%82%AC'
1 'a=1'
'1' 'a=1'
u'1' 'a=1'
u'\x80'
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "C:\python27\lib\urllib.py", line 1282, in urlencode
v = quote_plus(str(v))
UnicodeEncodeError: 'ascii' codec can't encode character u'\x80' in position 0: ordinal not in range(128)

最后两个测试证明了 urlencode() 的问题。现在让我们看看 str 测试。

如果您坚持混合使用,那么您至少应该确保 str 对象以 UTF-8 编码。

'\x80' 是可疑的——它不是 any_valid_unicode_string.encode('utf8') 的结果。
'\xe2\x82\xac' 可以;这是 u'\u20ac'.encode('utf8') 的结果。
'1' 是可以的——所有 ASCII 字符在输入到 urlencode() 时都可以,如果需要,它将进行百分比编码,例如 '%'。

这是一个建议的转换器功能。它不会改变输入字典以及返回它(就像你的那样);它返回一个新的字典。如果值是 str 对象但不是有效的 UTF-8 字符串,它会强制异常。顺便说一句,您对它不处理嵌套对象的担忧有点误导 - 您的代码仅适用于 dicts,而嵌套 dicts 的概念并没有真正发挥作用。

def encoded_dict(in_dict):
out_dict = {}
for k, v in in_dict.iteritems():
if isinstance(v, unicode):
v = v.encode('utf8')
elif isinstance(v, str):
# Must be encoded in UTF-8
v.decode('utf8')
out_dict[k] = v
return out_dict

这是输出,以相反的顺序使用相同的测试(因为这次讨厌的测试在前面):

>>> for test in tests[::-1]:
... print repr(test), repr(urllib.urlencode(encoded_dict({'a':test})))
...
u'\u20ac' 'a=%E2%82%AC'
u'\x80' 'a=%C2%80'
u'1' 'a=1'
'1' 'a=1'
1 'a=1'
'\xe2\x82\xac' 'a=%E2%82%AC'
'\x80'
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 8, in encoded_dict
File "C:\python27\lib\encodings\utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte
>>>

这有帮助吗?

关于python - urllib.urlencode 不喜欢 unicode 值 : how about this workaround?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6480723/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com