如果“env”参数包含unicode对象,为什么Popen在Windows上失败?

时间:2012-09-03 19:18:28

标签: python windows

考虑这个例子:

>>> 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

2 个答案:

答案 0 :(得分:13)

如错误消息所示,环境必须只包含字符串。您的第一个Popen调用满足此条件,但第二个调用不满足,因为您将PATH映射到使用u"..."语法创建的Unicode对象。

请注意,通过回溯判断,您使用的是Python 2.6,因此链接代码实际上并不适用,因为它来自Python 3.3.0 beta2Popen检查对象是否为unicode对象,这在Python 3中是有意义的,其中字符串(内部实现为)unicode对象。但是,在Python 2.6中,the equivalent line正在使用PyUnicode_Check,这会使您在第二个示例中失败。

答案 1 :(得分:2)

当为pyspark配置jupyter内核时,我有类似的情况:kernel.json被读作unicode,然后打包到** kwargs传递给C = \ Anaconda2中的proc = Popen(cmd,** kwargs) Lib \ site-packages \ jupyter_client \ launcher.py

因此,我必须像这样修改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"
        )