子进程命令编码



我目前正在将脚本从Perl迁移到Python3(3.6.5)。在 Windows Server 2016 上运行。脚本使用参数构建命令行,并使用subprocess.check_output执行创建的字符串。其中一个参数选项称为-location:"my street"。该位置可以包含特殊字符,如变音符号 (äöß) 或 (áŠ)。

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

Perl 脚本以 UTF-8 模式运行

use UTF8;
binmode( STDOUT, ":utf-8" );

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

# -*- coding: utf-8 -*-

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

-location:"HQ/äöööStraße".

Perl 代码看起来像这样:

$command = "C:\PROGRAM FILES\Application\bin\cfg.exe"
$operand = "-modify -location:123á456ß99"
$result  = `$command $operand`;

Python 代码如下所示:

# -*- coding: utf-8 -*-
import subprocess
result = subprocess.check_output(['C:\PROGRAM FILES\Application\bin\cfg.exe', "-modify", "-location:123á456ß99"], shell=False, stderr=subprocess.STDOUT)

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

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

这个关键字基本上是说"只使用我的系统上默认的任何编码"(所以基本上在任何相当现代的东西上都是 UTF-8,除了在 Windows 上,你从系统的默认代码页的

深渊中获得一些克苏鲁暴行)。

如果没有这个关键字,子进程在Python 3中接收和返回bytes

当然,如果你知道编码,你也可以单独.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')

运行脚本的诀窍是将参数编码为"utf8",然后将它们解码为"ansi"。

command = r'C:PROGRAM FILESApplicationbincfg.exe'
argument = ["-modify", "-location:123á456ß99"]
argument_ansi = []
for x in argument:
argument_ansi.append(x.encode('utf-8').decode('ansi', 'replace'))
cmd = [command]
cmd.extend(argument_ansi)
result = subprocess.check_output(cmd, shell=False, encoding="utf-8", universal_newlines=True)

最新更新