python - 在 Windows 中处理 unicode 子进程环境的正确方法是什么?

标签 python windows python-2.7

以这个示例片段为例。

import subprocess
import os

env = os.environ.copy()
env["FOO"] = u"foo"
subprocess.check_call(["ls", "-l"], env=env)

在 Windows 上,这会失败。

C:\Python27\python.exe test.py
Traceback (most recent call last):
  File "test.py", line 7, in <module>
    subprocess.check_call(["ls", "-l"], env=env)
  File "C:\Python27\lib\subprocess.py", line 535, in check_call
    retcode = call(*popenargs, **kwargs)
  File "C:\Python27\lib\subprocess.py", line 522, in call
    return Popen(*popenargs, **kwargs).wait()
  File "C:\Python27\lib\subprocess.py", line 710, in __init__
    errread, errwrite)
  File "C:\Python27\lib\subprocess.py", line 958, in _execute_child
    startupinfo)
TypeError: environment can only contain strings

sys.pathdocumented与unicode完全没问题。处理这个(和类似代码)以便一切按预期工作的正确方法是什么?显而易见的解决方案是在 unicode 路径上调用 .encode(),但我不确定这是否会导致意外行为。

最佳答案

在 Windows 上,将环境指令传递给 subprocess.check_call() 归结为将环境传递给 CreateProcess()。那一个实际上可以采用 unicode 字符串(在其 CreateProcessW() 化身中)。

然而,从 python 2.7 的 _subprocess.c:

/* TODO: handle unicode command lines? */
/* TODO: handle unicode environment? */

所以你不是第一个想到这个问题的。

您的问题也没有通用的解决方案,因为环境由被调用进程解释,其中一些也由系统或系统库自动解释。因此,正确的编码取决于目标进程的期望。

不幸的是,虽然 Windows 上的 Python 2 确实处理 Unicode,但它实际上传递的是零终止的窄字符串(即 PyString_AS_STRING() 返回 char *) , 到系统功能。

现在,Windows 本身如何处理两个不同版本的环境变量,因为显然似乎可以传递宽或窄环境字符串。

目标进程只能访问 GetEnvironmentStrings(),它会返回宽字符或窄字符,具体取决于应用程序是在编译时是否支持 Unicode。

那么,当您从窄 (ANSI) 进程执行 CreateProcess() 以启动 Unicode 进程时,会发生什么?所有参数都会发生同样的事情,它们在调用者的代码页中被解码并转换为 Windows 版本的 UCS-2 宽字符。

所以正确的方法可能是使用系统代码页,因为只有这样字符串才能真正正确地出现在 unicode 目标进程中。这当然会阻止您使用不在该代码页中的字符 ...

是的,Python 2 上的 Unicode 环境或多或少已经损坏。

关于python - 在 Windows 中处理 unicode 子进程环境的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29429008/

相关文章:

windows - 哪个 python 可以访问 Quantlib 的预编译版本?

python - 用线条粗细在Python PIL中绘制椭圆

python - PySpark 将 DataFrame 保存到实际的 JSON 文件

python - 使用 timedelta.round() 函数

java - 如何在Windows操作系统上部署Twitter Heron?

python - glob.iglob 从文件名中删除路径

python - 将 Unicode 流重新编码为 Ascii 忽略错误

Python和Arduino串口,解码问题

python - 使用 IAM 角色使用 Python 连接到 Redshift

windows - PsExec 抛出错误消息,但工作没有任何问题