2012-09-03 8 views
9

Considere este ejemplo:¿Por qué falla Popen en Windows si el parámetro "env" contiene un objeto Unicode?

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

He rastreado el error de este código CPython:

http://hg.python.org/cpython/file/ca54c27a9045/Modules/_winapi.c#l511

Soy incapaz de udnerstand lo PyUnicode_Check hace, sin embargo:

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

+0

Así que sugieren el uso de Python 3 va a resolver este error Por favor consejo. Como yo también estoy enfrentando este problema, https://github.com/django-dbbackup/django-dbbackup/issues/147 –

Respuesta

11

Como dice el mensaje de error, el medio ambiente t solo debe contener cadenas. Su primera llamada a Popen cumple esta condición, pero la segunda no lo hace porque está mapeando PATH en un objeto Unicode creado con la sintaxis u"...". Utilice únicamente cadenas de bytes al proporcionar dictados de entorno al Popen y no obtendrá este error.

Tenga en cuenta que, a juzgar por el rastreo, está utilizando Python 2.6, por lo que el código vinculado no se aplica de hecho, ya que proviene de Python 3.3.0 beta2. PyUnicode_Check comprueba que el objeto sea unicode, lo que tiene sentido en Python 3, donde las cadenas son (implementadas internamente como) objetos unicode. En Python 2.6, sin embargo, the equivalent line está usando PyString_Check, lo que lo haría fallar en su segundo ejemplo.

0

Tuve una situación similar al configurar jupyter kernel para pyspark: kernel.json se lee como unicode, y luego se empaqueta en ** kwargs pasado a proc = Popen (cmd, ** kwargs) en C: \ Anaconda2 \ Lib \ site-packages \ jupyter_client \ launcher.py

Por lo tanto, tuve que modificar el launcher.py así:

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" 
     ) 
Cuestiones relacionadas