Ayr*_*yrx 3 python windows python-2.7
以这个示例片段为例。
import subprocess
import os
env = os.environ.copy()
env["FOO"] = u"foo"
subprocess.check_call(["ls", "-l"], env=env)
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
sys.path据证明,使用unicode完全可以。什么可以正确处理此代码(及类似代码)?显而易见的解决方案是调用.encode()unicode路径,但是我不确定这是否会导致意外行为。
在Windows上,将环境dict传递subprocess.check_call()归结为将环境传递给CreateProcess()。那实际上可以采用unicode字符串(以其CreateProcessW()形式)。
但是,从python 2.7的_subprocess.c:
/* TODO: handle unicode command lines? */
/* TODO: handle unicode environment? */
Run Code Online (Sandbox Code Playgroud)
因此,您不是第一个想到这个问题的人。
对于您的问题,也没有通用的解决方案,因为环境是由被调用的进程解释的,并且其中的某些环境也会由系统或系统库自动进行解释。因此,正确的编码取决于目标进程的期望。
不幸的是,尽管Windows上的Python 2确实处理Unicode,但实际上将零终止的窄字符串(即PyString_AS_STRING()return char *)传递给系统函数。
现在,Windows本身如何处理两种不同版本的环境变量,因为显然可以传递宽或窄环境字符串。
目标进程只能访问GetEnvironmentStrings()它,返回的是宽字符还是窄字符,这取决于应用程序是否使用Unicode支持进行编译。
那么,当您CreateProcess()从狭窄(ANSI)进程启动Unicode进程时会发生什么呢?所有参数都发生同样的事情,它们在调用者的代码页中被解码,并转换为Windows版本的UCS-2宽字符。
因此,正确的方法可能是使用系统代码页,因为只有这样,字符串才能真正在unicode目标进程中正确显示。当然-这可以防止您使用不在该代码页中的字符...
因此,是的,Python 2上的Unicode环境或多或少受到破坏。