处理命令行参数中的 unicode 字符
Processing unicode characters in command line arguments
我在 Raspberry Pi(Raspbian 基于 Debian Linux OS)上有一个项目,我必须将命令行参数传递给 Python 3节目。我需要能够传递一个 unicode 字符串。
我不确定应该如何设置。很明显,在将数据传递给 Python.
之前,命令行字符串要经过几次转换
让我们从我在终端会话中按下所需的击键时可以正确看到 Unicode 字符这一事实开始。这是一些测试代码:
$ echo "ā" > test.txt
$ cat test.txt
ā
$ hexdump test.txt
0000000 81c4 000a
0000003
那个 0x81c4 字,或双字节序列 0xc4+0x81 被“ā”编码为 UTF-8。
现在,如果我尝试将相同的字符传递给 Python,我会得到一个包含奇怪字符代码的双字符字符串:
import sys
param = sys.argv[1]
print([hex(ord(char)) for char in param])
$ python test.py ā
['0xdcc4', '0xdc81']
可以注意到,字符编码与0xc4+0x81字节序列相关,但这里每个字节都加上0xdc00。
如果我进入交互式控制台,unicode字符操作与普通字符一样:
>>> txt = 'ā'
>>> len(txt)
1
>>> hex(ord(txt[0]))
'0x101'
0x101 是字符“ā”的正确代码点。
所以,我的问题是,如何可靠地将双字符 ['0xdcc4', '0xdc81']
字符串转换为单字符字符串“ā”,从而在所有平台上都适用?
我不确定这到底是在哪一点发生的,但是命令行参数显然应该只包含 ASCII 字符,并且要将字节数组解码为字符串,使用 bytes.decode(encoding, errors):
param = b'\xc4\x81'.decode('ASCII', 'surrogateescape')
print(param == '\udcc4\udc81') # True
当解码器偶然发现非 ASCII 字符时,它会根据选定的错误处理程序处理解码。在这种情况下,surrogateescape
错误处理程序将字节替换为从 U+DC80 到 U+DCFF 的单个代理代码。
因此,解决此问题的方法是使用相同的 surrogateescape
错误处理程序将错误解码的字符串编码回字节数组,然后将其解码为 utf-8
:
import sys
param = sys.argv[1]
param_unicode = param.encode('ASCII', 'surrogateescape').decode('utf-8')
print(param_unicode)
$ python test.py ā
ā
但是,如果命令行参数真的总是使用 ASCII 编码解码,则应该验证一下。可能不同平台不一样,可以配置。
我在 Raspberry Pi(Raspbian 基于 Debian Linux OS)上有一个项目,我必须将命令行参数传递给 Python 3节目。我需要能够传递一个 unicode 字符串。
我不确定应该如何设置。很明显,在将数据传递给 Python.
之前,命令行字符串要经过几次转换让我们从我在终端会话中按下所需的击键时可以正确看到 Unicode 字符这一事实开始。这是一些测试代码:
$ echo "ā" > test.txt
$ cat test.txt
ā
$ hexdump test.txt
0000000 81c4 000a
0000003
那个 0x81c4 字,或双字节序列 0xc4+0x81 被“ā”编码为 UTF-8。
现在,如果我尝试将相同的字符传递给 Python,我会得到一个包含奇怪字符代码的双字符字符串:
import sys
param = sys.argv[1]
print([hex(ord(char)) for char in param])
$ python test.py ā
['0xdcc4', '0xdc81']
可以注意到,字符编码与0xc4+0x81字节序列相关,但这里每个字节都加上0xdc00。
如果我进入交互式控制台,unicode字符操作与普通字符一样:
>>> txt = 'ā'
>>> len(txt)
1
>>> hex(ord(txt[0]))
'0x101'
0x101 是字符“ā”的正确代码点。
所以,我的问题是,如何可靠地将双字符 ['0xdcc4', '0xdc81']
字符串转换为单字符字符串“ā”,从而在所有平台上都适用?
我不确定这到底是在哪一点发生的,但是命令行参数显然应该只包含 ASCII 字符,并且要将字节数组解码为字符串,使用 bytes.decode(encoding, errors):
param = b'\xc4\x81'.decode('ASCII', 'surrogateescape')
print(param == '\udcc4\udc81') # True
当解码器偶然发现非 ASCII 字符时,它会根据选定的错误处理程序处理解码。在这种情况下,surrogateescape
错误处理程序将字节替换为从 U+DC80 到 U+DCFF 的单个代理代码。
因此,解决此问题的方法是使用相同的 surrogateescape
错误处理程序将错误解码的字符串编码回字节数组,然后将其解码为 utf-8
:
import sys
param = sys.argv[1]
param_unicode = param.encode('ASCII', 'surrogateescape').decode('utf-8')
print(param_unicode)
$ python test.py ā
ā
但是,如果命令行参数真的总是使用 ASCII 编码解码,则应该验证一下。可能不同平台不一样,可以配置。