考虑这个例子:
>>> import subprocess as sp
>>> sp.Popen("notepad2.exe",env={"PATH":"C:\\users\\guillermo\\smallapps\\bin"})
<subprocess.Popen object at 0x030DF430>
>>> sp.Popen("notepad2.exe",env={"PATH":u"C:\\users\\guillermo\\smallapps\\bin"})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python26\lib\subprocess.py", line 633, in __init__
errread, errwrite)
File "C:\Python26\lib\subprocess.py", line 842, in _execute_child
startupinfo)
TypeError: environment can only contain strings
我已将此错误追溯到此CPython代码:
http://hg.python.org/cpython/file/ca54c27a9045/Modules/_winapi.c#l511
我无法完成PyUnicode_Check
所做的事情,但是:
http://hg.python.org/cpython/file/26af48f65ef3/Objects/unicodeobject.c#l73
答案 0 :(得分:13)
如错误消息所示,环境必须只包含字符串。您的第一个Popen
调用满足此条件,但第二个调用不满足,因为您将PATH
映射到使用u"..."
语法创建的Unicode对象。 1}}提供环境词典时只使用字节字符串,您不会收到此错误。
请注意,通过回溯判断,您使用的是Python 2.6,因此链接代码实际上并不适用,因为它来自Python 3.3.0 beta2。 Popen
检查对象是否为unicode对象,这在Python 3中是有意义的,其中字符串是(内部实现为)unicode对象。但是,在Python 2.6中,the equivalent line正在使用PyUnicode_Check
,这会使您在第二个示例中失败。
答案 1 :(得分:2)
因此,我必须像这样修改launcher.py:
try:
# Ihor Bobak: fix to convert all env keys and values to str
klist = kwargs['env'].keys()[:]
for key in klist:
value = kwargs['env'][key]
if isinstance(key, unicode) or isinstance(value, unicode):
newkey = key.encode('ascii','ignore')
newvalue = value.encode('ascii','ignore')
del kwargs['env'][key]
kwargs['env'][newkey] = newvalue
# regular code
proc = Popen(cmd, **kwargs)
except Exception as exc:
msg = (
"Failed to run command:\n{}\n"
" PATH={!r}\n"
" with kwargs:\n{!r}\n"
)