2012-09-03 12 views
9

Considerate questo esempio:Perché Popen non funziona su Windows se il parametro "env" contiene un oggetto 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 

ho fatta risalire l'errore a questo codice CPython:

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

Sono in grado di udnerstand quello PyUnicode_Check fa, però:

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

+0

Così vi proponiamo utilizzando Python 3 sarà risolvere il problema si prega di consulenza. Poiché sto affrontando questo problema, https://github.com/django-dbbackup/django-dbbackup/issues/147 –

risposta

11

Come dice il messaggio di errore, l'ambiente t deve contenere solo stringhe. La prima chiamata Popen soddisfa questa condizione, ma la seconda non avviene perché si sta mappando PATH in un oggetto Unicode creato con la sintassi u"...". Utilizzare solo le stringhe di byte quando si fornisce l'ambiente dettato a Popen e non si otterrà questo errore.

Si noti che, a giudicare dal traceback, si sta utilizzando Python 2.6, quindi il codice collegato non si applica in realtà, perché viene da Python 3.3.0 beta2. PyUnicode_Check verifica che l'oggetto sia un oggetto Unicode, il che ha senso in Python 3, dove le stringhe sono (implementate internamente come) oggetti unicode. In Python 2.6, tuttavia, the equivalent line utilizza PyString_Check, che potrebbe non riuscire nel secondo esempio.

0

Ho avuto una situazione simile quando configurato kernel jupyter per pyspark: il kernel.json viene letto come unicode, e quindi impacchettato in ** kwargs passato a proc = Popen (cmd, ** kwargs) in C: \ Anaconda2 \ lib \ site-packages \ jupyter_client \ launcher.py

Pertanto, ho dovuto modificare il launcher.py in questo modo:

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" 
     ) 
Problemi correlati