11

考虑这个例子:

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

4

2 回答 2

13

正如错误消息所说,环境只能包含字符串。您的第一个Popen调用满足此条件,但第二个调用不满足此条件,因为您正在映射到使用该语法PATH创建的 Unicode 对象。u"..."提供环境字典时仅使用字节字符串Popen,您不会收到此错误。

请注意,根据回溯判断,您使用的是 Python 2.6,因此链接代码实际上并不适用,因为它来自Python 3.3.0 beta2PyUnicode_Check检查该对象是否为 unicode 对象,这在 Python 3 中是有意义的,其中字符串(内部实现为)unicode 对象。但是,在 Python 2.6 中,等效的行是 using PyString_Check,这将使其在您的第二个示例中失败。

于 2012-09-03T19:27:24.247 回答
3

我在为 pyspark 配置 jupyter 内核时遇到了类似的情况: kernel.json 被读取为 unicode,然后打包到 **kwargs 传递给 C:\Anaconda2\Lib\site 中的 proc = Popen(cmd, **kwargs) -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"
        )
于 2017-12-13T16:40:47.157 回答