以这个示例片段为例。
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.path
是 documented与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/