如何使用OptParse获取包含非ASCII字符的字符串?

6

我正在使用 OptParse 模块来获取一个字符串值。但是,OptParse 仅支持 str 类型的字符串,而不支持 unicode

假设我用以下代码启动我的脚本:

./someScript --some-option ééééé

在代码中读取由str输入的法语字符,例如' é ',会触发UnicodeDecodeError

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 99: ordinal not in range(128)

我尝试了一下内置的unicode函数,但是要么出现错误,要么字符消失:

>>> unicode('é');
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
>>> unicode('é', errors='ignore');
u''

我该如何使用 OptParse 获取 unicode/utf-8 字符串?

似乎可以成功获取并打印该字符串,但是当尝试使用 SQLite (使用 APSW 模块) 时,它会尝试通过 cursor.execute("...") 进行某种方式的转换,然后错误就会发生。

这里是一个导致错误的示例程序:

#!/usr/bin/python
# coding: utf-8

import os, sys, optparse
parser = optparse.OptionParser()
parser.add_option("--some-option")
(opts, args) = parser.parse_args()
print unicode(opts.some_option)

Str对象只是字节存储,因此如果输入为UTF-8,则字符串将保存UTF-8值。Unicode错误在哪里抛出? - Alastair McCormack
我刚在UTF-8控制台上测试了这个,optparse正常工作并将字符返回到控制台。您能否澄清这个错误是在您的代码中还是在optparse中? - Alastair McCormack
你的程序是依赖于optparse还是从头开始构建的?如果是后者,我建议使用docopts包而不是optparse。你会非常惊讶它是如何轻松地解析命令行参数的。 - Bruce
@Fuzzyfelt:多亏了你的第二条评论,我已经将我的问题缩小了一些。 - user610650
4个回答

4

在解析器处理参数之前,您可以对其进行解码。以您的示例为例:

#!/usr/bin/python
# coding: utf-8
import os, sys, optparse
parser = optparse.OptionParser()
parser.add_option("--some-option")

# Decode the command line arguments to unicode
for i, a in enumerate(sys.argv):
    sys.argv[i] = a.decode('ISO-8859-15')

(opts, args) = parser.parse_args()
print type(opts.some_option), opts.some_option

这会得到以下输出:
C:\workspace>python file.py --some-option préférer
<type 'unicode'> préférer

我选择了ISO/IEC 8859-15代码页,因为它似乎最适合您。如果需要,请进行调整。


1
为了避免硬编码编码方式,您可以尝试像这样猜测它:locale.getpreferredencoding()(导入locale)。 - Stan
顺便提一下,你可能需要使用unicode(a.decode("your_encoding_here"))将其转换为Unicode编码。 - Stan

1

输入以控制台编码返回,因此根据您的更新示例使用:

print opts.some_option.decode(sys.stdin.encoding)

unicode(opts.some_option) 默认使用 ascii 作为编码。


0

我相信你的错误与以下内容有关:

例如,要编写包含欧元货币符号的Unicode文字,可以使用ISO-8859-15编码,其中欧元符号具有序数值164。此脚本将打印值8364(对应于欧元符号的Unicode代码点),然后退出:

# -*- coding: iso-8859-15 -*-

currency = u"€"
print ord(currency)

0
#!/usr/bin/python
# coding: utf-8

import os, sys, optparse

reload(sys)
sys.setdefaultencoding('utf-8')

parser = optparse.OptionParser()
parser.add_option(u"--some-option")
(opts, args) = parser.parse_args()
print opts.print_help()

这对我似乎不起作用。你是在使用Python 2还是3?我正在运行Python 2.7。 - jersey bean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接