Unicode、Python3和程序员之间的又一场战斗。解码字符串
问题是将字节转换为unicode,而这些字节已经保存为字符串。以下是一个例子:Unicode、Python3和程序员之间的又一场战斗。解码字符串,python,unicode,python-3.x,encoding,utf-8,Python,Unicode,Python 3.x,Encoding,Utf 8,问题是将字节转换为unicode,而这些字节已经保存为字符串。以下是一个例子: s1 = '\xd0\xb1\xd0\xb0' s2 = b'\xd0\xb1\xd0\xb1' print(s1) # Here is the problem: prints a trash (аб) print(s2.decode('utf-8')) # Everything is OK, printing 'ба' (two cyrillic symbols) 但是现在如何解码s1中的数据?我不
s1 = '\xd0\xb1\xd0\xb0'
s2 = b'\xd0\xb1\xd0\xb1'
print(s1) # Here is the problem: prints a trash (аб)
print(s2.decode('utf-8')) # Everything is OK, printing 'ба' (two cyrillic symbols)
但是现在如何解码s1中的数据?我不能在s1声明之前添加b'修饰符,因为s1可能来自互联网,所以我不能像声明s2那样声明s1。
我发现b'修饰符的工作原理类似于bytes()函数,但当我试图调用它时:
s3 = bytes(s1, 'utf-8')
又是一个垃圾桶:
print(s3.decode('utf-8')) # аб
所以问题是:我应该如何处理s1使其成为终端输出中的“ба”
我在谷歌上搜索了很多,但我发现的并不是我需要的
这就是我需要的:
s4 = SOME_WONDERFUL_MAGIC(s1)
print(s4) # Prints 'ба'
非常感谢所有能帮助我的人,请原谅我英语不好
更新:Oops,问题返回。我希望第一个答案会对我有所帮助,但我发现:
s1 == '\xd0\xb1\xd0\xb0' # BUT
s1 != '\xd0\xb1\xd0\xb0'
我的意思是:
我使用“requests”包向Flask服务器发出POST请求。它回答我:
req = requests.post(hostName)
print(req.text) # b'testText'
# BUT!
print(req.text[2:-1] # testText
这意味着testText的字节表示形式为字符串,如下所示:
s5 = "b'tumba'"
所以真正的问题是:如何从b'tumba'中提取tumba(如果tumba可能包含西里尔字母符号)?快速而肮脏的解决方案,对我有效:
s1 = '\xd0\xb1\xd0\xb0'
s4 = bytes(s1, encoding='latin1').decode('utf-8')
print(s4)
s1
可能被错误地解码为某处
您可以尝试重新编码
>>> s4 = s1.encode('ISO-8859-1')
>>> s4.decode('UTF-8')
'ба'
你真正的错误是找到解码发生的地方
停止互换处理unicode和字节,战斗就会停止:)unicode对象如何“来自互联网”?如果它来自互联网,它是字节。它在某处被解码为unicode,问题是在哪里?@gnibler:可能“来自互联网”的意思是“来自stdlib中的一个互联网相关模块或其他地方,它们在我背后解码了它”。当然,在这种情况下,OP必须告诉我们他使用了哪个模块,我们可以告诉他如何显式地设置编码,而不是默认为不正确的编码,这将解决问题,而不需要任何奇妙的魔法。@abarnert,这正是我所尝试的say@gnibbler:是的,你的观点很关键;我只是不确定一个新手会理解它。新手通常不会直接从
sock.read()
处理数据,并且可能没有意识到请求或ElementTree
或任何正在使用默认值或猜测的东西。对于每个询问unicode对象源的人来说,这是Flask server的响应。”“请求”包用于发出请求。但是没有更多的问题:gnibbler回答了一个问题,非常格拉茨。当然,但是如果你有“来自互联网”的数据,并且这次被错误地解码为拉丁-1,那么你编写代码对其重新编码只是为了正确地解码,当下一段数据被错误地解码为其他数据时,这一切都将失败。如果不知道它是如何被错误解码的,你就无法解决这个问题。如果你不知道你有什么(编码),那么很难猜测编码,即使你这样做了,也总是有失败的可能性。所以,我只是假设它是UTF-8。你没有抓住重点。我们可以假设实际字节是UTF-8,因为OP是这么说的。我们不能假设字节被拉丁语-1错误解码,而不是,比如说,用sys.getdefaultencoding()
(这会使你的代码在其他机器上中断),或者(这会使它在不同的数据中中断),等等。我为测试字符串工作,但现实生活中出现了一个新问题,这让我感到惊讶(问题更新了).