【问题标题】:How do I tell Python that sys.argv is in Unicode?我如何告诉 Python sys.argv 是 Unicode 格式的?
【发布时间】:2011-02-25 04:29:44
【问题描述】:

这是一个小程序:

import sys

f = sys.argv[1]
print type(f)
print u"f=%s" % (f)

这是我运行的程序:

$ python x.py 'Recent/רשימת משתתפים.LNK'
<type 'str'>
Traceback (most recent call last):
  File "x.py", line 5, in <module>
    print u"f=%s" % (f)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 7: ordinal not in range(128)
$ 

问题在于 sys.argv[1] 认为它正在获取一个无法转换为 Unicode 的 ascii 字符串。但是我使用的是带有完整 Unicode 感知终端的 Mac,所以 x.py 实际上得到了一个 Unicode 字符串。我如何告诉 Python sys.argv[] 是 Unicode 而不是 Ascii?如果做不到这一点,如何将 ASCII(其中包含 unicode)转换为 Unicode?明显的转换不起作用。

【问题讨论】:

标签: python macos unicode terminal


【解决方案1】:

您看到的UnicodeDecodeError 错误是由于您混合了Unicode 字符串u"f=%s"sys.argv[1] 字节串:

  • 两个字节串:

      $ python2 -c'import sys; print "f=%s" % (sys.argv[1],)' 'Recent/רשימת משתתפים'
    

    这会透明地从/向您的终端传递字节。它适用于任何编码。

  • 都是 Unicode:

      $ python2 -c'import sys; print u"f=%s" % (sys.argv[1].decode("utf-8"),)' 'Rec..
    

    这里你应该用你的终端使用的编码替换'utf-8'。如果终端不支持 Unicode,您可以在此处使用 sys.getfilesystemencoding()

两个命令产生相同的输出:

f=Recent/רשימת משתתפים

一般来说,您应该尽快将您认为是文本的字节串转换为 Unicode。

【讨论】:

  • 其实我发现了问题所在。事实证明,Python 不是将 utf-8 视为 Unicode,而是视为 ASCII。尝试print type(u"foobar".encode('utf-8')) and you'll get str`,而不是输入unicode
  • @vy32: 'utf-8' 是一种字符编码。在任何情况下它都不是 Unicode。 .encode() 方法可以将 Unicode 字符串(文本)转换为字节串(数据)。您对 Unicode 是什么有一些误解。请阅读joelonsoftware.com/articles/Unicode.html
  • 谢谢。事实上,我已经读过了。问题是作者的断言“关于编码的最重要的事实——在不知道它使用什么编码的情况下拥有一个字符串是没有意义的。”在我的工作领域中,在不知道它们使用的编码的情况下拥有字符串是很常见的。我们还在中间看到了改变编码的字符串。
  • @vy32:如果您不知道编码,则输入可能不明确,例如 "Bush hid the facts"Garbage in, garbage out
  • sys.getfilesystemencoding() 是救生员。谢谢!
【解决方案2】:
sys.argv = map(lambda arg: arg.decode(sys.stdout.encoding), sys.argv)

或者你可以从locale.getdefaultlocale()[1]中选择编码

【讨论】:

    【解决方案3】:

    使用用于启动 Python 的 shell 上的编码将命令行参数作为字节字符串传递给 Python。因此,除了将参数 yourself 转换为应用程序中的 unicode 之外,没有办法将命令行参数作为 unicode 字符串传递给 Python。

    【讨论】:

    • 您不必自己转换参数。如果操作系统提供,Python 可以使用广泛的 API。 sys.argv 是 Python3 中的 Unicode 字符串。
    • @J.F Sebastian +1 使用 Python 3!在 Python @vy32 的版本中使用 arg 确实必须在 shell 中转换,正如我在下面的答案中或在代码中或升级到 python 3!
    • @mkelley33:我的意思是说:原则上,您不必自己转换参数。这只是 CPython2 实现的一个不足。 Python3 只是一个软件可以为你做的例子。 Python3 至少在几年内还没有准备好被广泛采用。我没有说你应该使用它。
    • @J.F. Sebastian:了解我的朋友,但你当然应该使用它(Python3)!我必须检查项目需要哪些依赖项,以及哪些限制可能会对正在考虑的 Python 版本的任何开发产生不利影响。尽管 Python3 仍有许多包不可用,但我不建议 @pynator 等待数年才能使用它,除非相关项目表现出某种程度的复杂性,可能需要尚未为 Python 准备好的依赖项3 :) 干杯!
    【解决方案4】:

    试试:

    f = sys.argv[1].decode('utf-8')
    

    或:

    f = unicode(sys.argv[1], 'utf-8')
    

    【讨论】:

      【解决方案5】:
      1. sys.argv 永远不是“Unicode”;它肯定是编码的,但 Unicode 不是一种编码,而是一组代码点(数字),其中每个数字唯一地代表一个字符。 http://www.unicode.org/standard/WhatIsUnicode.html

      2. 进入 Terminal.app > Terminal > Preferences > Settings > Character encoding,然后从下拉列表中选择 UTF-8。

      3. 此外,Mac OS X 附带的默认 Python 在 Unicode 方面存在一个缺陷:它默认使用已弃用的 UCS-2 构建;见:http://webamused.wordpress.com/2011/01/31/building-64-bit-python-python-org-using-ucs-4-on-mac-os-x-10-6-6-snow-leopard/

      【讨论】:

      • 要测试 #2,请转到系统偏好设置 > 语言和文本 > 输入源 > 标记选中 Unicode 十六进制输入。打开一个交互式解释器会话,现在输入 alt(选项)+ 00a9。如果您看到 © 版权符号,那么您的终端输入是 UTF-8 编码的,但您可能仍需要使用 UCS-4 选项构建 Python。
      • 事实证明,Python 认为 UTF-8 是 ASCII,而不是 Unicode。天哪,我觉得这很混乱。
      • 注意:“每个字符都有一个唯一的数字”不等于每个“数字唯一地代表一个字符”。有细微的差别。后一个引用并不完全正确。一个代码点总是指向同一个字符,但一个字符可以使用代码点以不止一种方式表示。例如,U+00E9é U+0065 U+0301é 即,代码点不能唯一地表示一个字符,因此有 Unicode 规范化 unicode.org/reports/tr15 以避免二进制中的歧义Unicode 字符串的表示形式。
      • 虽然 Unicode 确实不是一种编码,但 Unicode确实包括编码(最显着的是 UTF-8)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 1970-01-01
      • 1970-01-01
      • 2014-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多