2012-09-03 35 views
9

考慮這個例子:如果「env」參數包含unicode對象,爲什麼Popen在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

我無法udnerstand什麼PyUnicode_Check做,雖然:

http://hg.python.org/cpython/file/26af48f65ef3/Objects/unicodeobject.c#l73

+0

所以你建議使用python 3將解決此錯誤,請諮詢。由於我太面臨這個問題https://github.com/django-dbbackup/django-dbbackup/issues/147 –

回答

11

正如錯誤消息所述,環境t只能包含字符串。您的第一個Popen調用滿足此條件,但第二個不會因爲您將PATH映射到使用u"..."語法創建的Unicode對象。將環境字典提供給Popen時僅使用字節字符串,並且不會出現此錯誤。

請注意,根據追溯來判斷,您使用的是Python 2.6,所以鏈接的代碼實際上並不適用,因爲它來自Python 3.3.0 beta2PyUnicode_Check檢查對象是否爲unicode對象,這在Python 3中是合理的,其中字符串(內部實現爲)unicode對象。但是,在Python 2.6中,the equivalent line正在使用PyString_Check,這會使其在第二個示例中失敗。

0

我在爲pyspark配置jupyter內核時有類似的情況:kernel.json被讀爲unicode,然後打包成** kwargs傳遞給C:\ Anaconda2中的proc = Popen(cmd,** kwargs) \ LIB \站點包\ 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" 
     ) 
相關問題