【问题标题】:Don't argparse read unicode from commandline?不要 argparse 从命令行读取 unicode 吗?
【发布时间】:2014-05-21 17:57:11
【问题描述】:

运行 Python 2.7

执行时:

$ python client.py get_emails -a "åäö"

我明白了:

usage: client.py get_emails [-h] [-a AREA] [-t {rfc2822,plain}]
client.py get_emails: error: argument -a/--area: invalid unicode value: '\xc3\xa5\xc3\xa4\xc3\xb6'

这是我的解析器:

def _argparse():
    desc = """
           Simple CLI-client for...
           """
    argparser = argparse.ArgumentParser(description=desc)
    subparsers = argparser.add_subparsers(dest='command')

    # create the parser for the "get_emails" command
    parser_get_emails = subparsers.add_parser('get_emails', help=u'Get email list')
    parser_get_emails.add_argument('-a', '--area', type=unicode, help='Limit to area')
    parser_get_emails.add_argument('-t', '--out_type', choices=['rfc2822', 'plain'],
                                   default='rfc2822', help='Type of output')

    args = argparser.parse_args()
    return args

这是否意味着我不能在 python argparse 模块中使用任何 unicode 字符?

【问题讨论】:

  • 你的终端编码是什么?
  • 您的终端使用 UTF-8 编码,但 Python 默认使用 ASCII,因此 unicode 使用错误的编码将字节转换为 unicode 对象。

标签: python unicode argparse


【解决方案1】:

你可以试试

type=lambda s: unicode(s, 'utf8')

而不是

type=unicode

没有编码参数 unicode() 默认为 ascii。

【讨论】:

  • 太好了,我明天再在电脑前测试一下。正在考虑使用lambda s: unicode(s, locale.getdefaultlocale()[1]) 我想这会更灵活。有什么注意事项吗?
  • @NiclasNilsson:getdefaultlocale 在某些情况下可以返回 None,None,所以你需要一个后备,比如 getdefaultlocale()[1] or 'utf8'
  • 编码可能不同。在这里使用sys.getfilesystemencoding() 而不是硬编码utf8
  • @NiclasNilsson:我对非 unicode 控制台几乎没有经验,但 here 人们说 getfilesystemencoding 不是 argv 编码。 可能sys.stdin.encoding
  • @georg:您提供的链接中没有提到sys.getfilesystemencoding()。为什么你认为sys.argv 的项目不在sys.getfilesystemencoding() 中?无法解码的参数存在问题,但这是一个不同的问题。
【解决方案2】:

命令行参数使用sys.getfilesystemencoding()进行编码:

import sys

def commandline_arg(bytestring):
    unicode_string = bytestring.decode(sys.getfilesystemencoding())
    return unicode_string

# ...
parser_get_emails.add_argument('-a', '--area', type=commandline_arg)

注意:在 Python 3 中不需要它(参数已经是 Unicode)。在这种情况下,它使用os.fsdecode(),因为有时命令行参数可能无法解码。见PEP 383 -- Non-decodable Bytes in System Character Interfaces

【讨论】:

  • 如果您需要支持在当前本地编码中无法解码的文件名(Windows 上的 Unicode API,Linux 上配置错误的区域设置),实际答案可能会更复杂。更多详情见Как работать с путями c русскими символами?(询问是否需要翻译)
  • 这对我有用。在我的例子中,参数值是一串汉字。接受的答案抱怨invalid <lambda> value:
猜你喜欢
  • 2015-07-26
  • 2018-04-26
  • 2016-12-20
  • 2014-11-09
  • 2021-06-26
  • 2016-05-02
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多