【问题标题】:How to decode unicode python arguments?如何解码 unicode python 参数?
【发布时间】:2014-11-14 08:36:45
【问题描述】:

使用以下代码(在 PHP 中)我将字符串发送到 python 程序:

shell_exec("python3 /var/www/html/app.py \"$text\"");

$text 变量包含非英语字符串。问题是,当我在 Python 中使用 print(sys.argv) 打印参数时,我得到如下结果:

['/var/www/html/app.py', '\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8\udcb4\udcda\udca9 \udcd8\udcae\udcd8\udcab\udcd9\udc87\udcd8\udca8 \udcd8\udcaa\udcd8\udcb4\udcd8\udcb5\udcd8\udcab'] 

如何将此 unicode 字符串转换为 python 中文本的原始形式?

【问题讨论】:

  • 你期望什么输出?这些代码点是代理。
  • @Wooble 我想在一个函数中使用这个文本,该函数适用于普通字符串而不是 unicode。

标签: php python linux python-3.x unicode


【解决方案1】:
shell_exec("python3 /var/www/html/app.py \"$text\"");

(我希望$text 被强力清理、转义或静态!如果用户输入进入这里,你就有一个可怕的远程代码执行漏洞!)

'\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8...

好的,这里发生的事情是 PHP 已将 UTF-8 编码的字符串传递给 Python,但 Python 不知道命令行输入是 UTF-8。 (通常当您将 Python 作为命令运行时,它可以从您的终端解决,但当 PHP 在 Web 服务器中运行 Python 时,没有终端。)

不知道输入是什么,它默认为纯 ASCII。输入中的高字节在 ASCII 中无效,但 Python 3 有一个用于无效字节的“surrogateescape”回退处理程序,在将其解码为 Unicode 字符串时应用于命令行。这会生成其他无效的 UTF-16 代理代码单元 U+DC80–U+DCFF,但如果您愿意,至少它允许恢复原始高字节。

所以要么:

  • 在执行 Python 之前将PYTHONIOENCODING 环境变量设置为UTF-8,这样它首先就知道正确的编码是什么,或者

  • 更改 Python 脚本以预处理其输入,以使用 sys.argv[1].encode('utf-8', 'surrogateescape').decode('utf-8') 恢复正确的输入

【讨论】:

  • PYTHONIOENCODINGsys.argv 没有影响。你应该使用相同的字符编码来编码(不要硬编码'utf-8'),就像Python用来解码sys.argv一样。
  • @bobince +1 感谢您的警告!将 PYTHONENCODING 设置为 utf-8 无效,但 LANG=en_US.utf-8 有效
【解决方案2】:

Python 使用您的语言环境编码来解码它从命令行获取的字节。默认 C 语言环境使用 ascii。 $text 似乎在 utf-8 中。因此,Python 必须使用 surrogateescape 错误处理程序将这些字节解码为文本 sys.argv[1],从而生成您在输出中看到的单独代理项,例如 '\udcd8'

您可以使用 utf-8 语言环境,例如 LC_ALL=C.UTF-8 或手动重新编码参数:sys.argv[1].encode(locale.getpreferredencoding(True), 'surrogateescape').decode('utf-8')

>>> s = u'\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8\udcb4\udcda\udca9 \udcd8\udcae\udcd8\udcab\udcd9\udc87\udcd8\udca8 \udcd8\udcaa\udcd8\udcb4\udcd8\udcb5\udcd8\udcab'
>>> print(s.encode('ascii', 'surrogateescape').decode('utf-8'))
بتصشک خثهب تشصث

【讨论】:

  • 手动重新编码参数时出现此错误:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
猜你喜欢
  • 2017-04-16
  • 2015-11-02
  • 2019-12-19
  • 2012-04-10
  • 2015-11-01
  • 2021-09-01
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多