Python如何正确打印cp1258越南语字符?

Python如何正确打印cp1258越南语字符?,python,encoding,Python,Encoding,如何在python 3中正确打印越南语cp1258编码字符?我的终端似乎不是问题所在,因为它将正确打印代码中的第一条打印语句。我正在尝试将十六进制字符解码为越南语 代码: 导入binascii 数据='tạ米碧ệ不 打印(数据)#ạ米碧ệT a=binascii.hexlify(data.encode('cp1258',errors='backslashcreplace')) 打印(a)#b'745c75316561316d2062695c753165633774' #如果我不在此处使用错误处理

如何在python 3中正确打印越南语
cp1258
编码字符?我的终端似乎不是问题所在,因为它将正确打印代码中的第一条打印语句。我正在尝试将十六进制字符解码为越南语

代码:

导入binascii
数据='tạ米碧ệ不
打印(数据)#ạ米碧ệT
a=binascii.hexlify(data.encode('cp1258',errors='backslashcreplace'))
打印(a)#b'745c75316561316d2062695c753165633774'
#如果我不在此处使用错误处理程序,则会得到\u1ea1的UnicodeEncodeError
印刷品(
binascii.unexlify(a).解码('cp1258')#t\u1ea1mbi\u1ec7t
)

Python对的支持中似乎有一个遗漏。传统的编解码器通过组合变音符号来支持越南语,但Python不知道如何将Unicode转换为这些组合。我想你必须自己进行转换

作为第一步,请注意
unicodedata.normalize('NFD',data)
将表示拆分为一个基本字符和一系列组合变音符号

unicodedata.normalize('NFD',data.encode('utf-8')) b'ta\xcc\xa3m bie\xcc\xa3\xcc\x82t' >>>“{0:04x}.”格式(ord(b'\xcc\xa3'.解码('utf-8')) '0323' 因此U+0323是下点的组合Unicode字符,编解码器应该知道这种对应关系(上面的Wikipedia页面链接显示了CP1258代码点0xF2的相同Unicode字符代码)

我对目标编解码器了解不多,无法告诉您如何将它们映射到CP1258,但如果您幸运的话,Python编解码器中已经有了这些的某种映射

我的Mojave MacOS上的iconv似乎可以顺利地将其转换为:


$iconv-tcp1258我猜出来了。使用
unicode转义
进行解码就可以做到这一点

导入binascii
数据=u'tạ米碧ệ不
打印(数据)#ạ米碧ệT
a=binascii.hexlify(data.encode('cp1258',errors='backslashcreplace'))
打印(a)#b'745c75316561316d2062695c753165633774'
#如果我不在此处使用错误处理程序,则会得到\u1ea1的UnicodeEncodeError
印刷品(
binascii.unexlify(a).解码('unicode-escape')#tạ米碧ệT
)

只是
打印(数据)
不做你想做的事吗?这实际上是关于您的系统是如何配置的——系统代码页是什么?您是否使用相同的配置设置了Python?从您的示例中很难知道您正在尝试做什么以及为什么。UnicodeEncodeError表示您有一个字符在字符集中根本不存在
cp1258
。我在这里尝试的是将十六进制解码为越南语字符。这就是为什么
print(data)
只是一个调试语句,以确保我的系统配置正确。@MarkRansom,我确信该字符存在,因为
cp1258
是特定于越南语的。有许多旧的代码页用于某些语言,但仍然没有包含所有常用字符集(缺少较少见的字符)。说得很好!我想你的意思是
'NFD'
,而不是
'NFC'
,但这仍然给你留下了一个编码问题。@Markranson谢谢,我注意到了同样的事情,brain fart。我在修复它的时候对这个主题进行了一些扩展。因此,似乎你已经发现了
cp1258
编解码器中的一个缺陷-我看不出有任何理由使用组合编码一个字符集中的字符不能转换成另一个字符集中的组合字符,只要转换是正式定义的。@tripleee想用python提交一个错误吗?这只是补偿了您自己创建的一个问题。它不太可能帮助解决最初导致您出现的问题。是的,您是对的。这个答案只需添加这是我在评论中提出的问题之一。
import subprocess

converted = subprocess.run(['iconv', '-t', 'cp1258'],
    input=data.encode('utf-8'), stdout=subprocess.PIPE).stdout