子进程命令编码

Jen*_*ens 1 python perl python-3.x

我目前正在将脚本从 Perl 迁移到 Python3 (3.6.5)。Is 在 Windows Server 2016 上运行。该脚本使用参数构建命令行,并使用subprocess.check_output. 参数选项之一称为-location:"my street"。该位置可以包含特殊字符,例如元音变音 (\xc3\xa4\xc3\xb6\xc3\x9f) 或 (\xc3\xa1\xc5\xa0)。

\n\n

当我运行 Perl 脚本时,特殊字符会正确传递到应用程序。当我运行 Python 脚本时,特殊字符将被应用程序中的问号替换。我认为被调用的应用程序需要一个 UTF-8 编码的参数字符串。

\n\n

Perl 脚本以 UTF-8 模式运行

\n\n
use UTF8;\nbinmode( STDOUT, ":utf-8" );\n
Run Code Online (Sandbox Code Playgroud)\n\n

Python脚本是用PyCharm创建的,UTF-8编码,脚本的第一行包含

\n\n
# -*- coding: utf-8 -*-\n
Run Code Online (Sandbox Code Playgroud)\n\n

我尝试了多种方法将子进程参数的编码设置为 UTF-8,但它不起作用。我曾经procmon.exe比较过 Perl 和 Python 脚本之间的应用程序调用。我可以看到,在 procmon 中为 Python 子进程调用显示的命令行对我来说是可读的。工作 Perl 调用不。在 procmon 中查找 perl 脚本的位置字符串如下所示:

\n\n

-location:"HQ/\xc3\x83\xc2\xa4\xc3\x83\xc2\xb6\xc3\x83\xc2\xb6\xc3\x83\xc2\xb6Stra\xc3\x83\xc5\xb8e"

\n\n

Perl 代码如下所示:

\n\n
$command = "C:\\\\PROGRAM FILES\\\\Application\\\\bin\\\\cfg.exe"\n$operand = "-modify -location:123\xc3\xa1456\xc3\x9f99"\n$result  = `$command $operand`;\n
Run Code Online (Sandbox Code Playgroud)\n\n

Python 代码如下所示:

\n\n
# -*- coding: utf-8 -*-\nimport subprocess\nresult = subprocess.check_output([\'C:\\\\PROGRAM FILES\\\\Application\\\\bin\\\\cfg.exe\', "-modify", "-location:123\xc3\xa1456\xc3\x9f99"], shell=False, stderr=subprocess.STDOUT)\n
Run Code Online (Sandbox Code Playgroud)\n\n

知道我必须做什么才能将 python 参数正确传递给应用程序吗?

\n

tri*_*eee 7

在 Python 3.3+ 中,您可以单独指示您期望特定编码的文本。关键字参数universal_newlines=True在 3.7 中被重命名为更准确和透明text=True

这个关键字基本上是说“只使用我系统上默认的任何编码”(所以基本上在任何相当现代的东西上都使用 UTF-8,除了 Windows 上,在 Windows 上你可以得到来自深渊的一些克苏鲁暴行系统的默认代码页)。

如果没有此关键字,子进程bytes在 Python 3 中接收并返回。

当然,如果你知道编码,你也可以单独.decode()返回bytes

如果您知道编码,那么使用关键字参数可能很有用encoding=(即使您假设它也是系统编码;这是在 Python 3.6 中添加的)。

response = subprocess.check_output([...], text=True)
response = subprocess.check_output([...], encoding='utf-8')
response = subprocess.check_output([...]).decode('utf-8')
Run Code Online (Sandbox Code Playgroud)