2016-10-02 2 views
1

Ich habe ein Programm, das von einem anderen Programm, das auf dem neuen Windows-Subsystem für Linux ausgeführt wird, ausgegeben wird. Ich habe ein Python-Programm geschrieben, das vom Windows-System läuft, aber das Linux-Programm mit Python-Subprozess-Modul ausführen wird. Wenn das verwirrend ist, sehen Sie das Beispiel unten.python subprocess.call() kann Windows Bash.exe nicht finden

Allerdings, wenn ich das tue, finde ich, dass, wenn durch Python-Subprozess aufgerufen, können Windows Bash-Programm nicht finden.

Beispiel auf der Kommandozeile oder Powershell in Windows:

C:\>bash -c "echo hello world!" 
hello world! 

C:\>python 
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import subprocess as s 
>>> s.call('bash -c "echo hello world"'.split()) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "c:\Python27-32\lib\subprocess.py", line 524, in call 
    return Popen(*popenargs, **kwargs).wait() 
    File "c:\Python27-32\lib\subprocess.py", line 711, in __init__ 
    errread, errwrite) 
    File "c:\Python27-32\lib\subprocess.py", line 948, in _execute_child 
    startupinfo) 
WindowsError: [Error 2] The system cannot find the file specified 

>>> s.call('bash -c "echo hello world"'.split(),shell=True) 
    'bash' is not recognized as an internal or external command, 
    operable program or batch file. 
    1 

Ich dachte, vielleicht war es nicht meinen Weg Einstellung Laden irgendwie so habe ich in der vollständigen Adresse des bash-Programms.

>>> s.call(b,shell=True) 
'C:\Windows\System32\bash.exe' is not recognized as an internal or external command, 
operable program or batch file. 
1 

EDIT: Ich weiß, mein Befehl könnte ein Problem, da o Uhr Splitting auf Räume werden zu geben und die „Echo Hallo Welt“ ist ein Argument, sondern versucht, die gleiche Sache mit bash -c ls gibt auch den gleichen Fehler

+0

@eryksun Danke, ich wusste, Bash war nur 64 Bit, aber dachte nicht, dass es zu dieser Art von Fehler führen würde, wenn es ein Kompatibilitätsproblem gab. Ich werde nur mein Programm mit der 64-Bit-Version von Python ausführen. Bitte setze das als Antwort, damit ich es annehmen kann! – jeffpkamp

+0

Randbemerkung: 's.call ('bash -c" echo hallo world "'. Split())' ist _wrong_. Sie haben das Programm gerade so aufgerufen, als wären "echo", "hallo" und "world" als drei separate Argumente übergeben worden. Wenn Sie unbedingt ein einzelnes String-Literal teilen müssen, verwenden Sie eine Funktion wie 'shlex.split', die Regeln zum Zitieren versteht. – ShadowRanger

Antwort

3

Für 32-Bit-Programme, die im WOW64-Subsystem ausgeführt werden, das Verzeichnis "System32" gets redirected für "SysWOW64". Der WSL-bash.exe-Loader wird als 64-Bit-Executable verteilt, daher müssen Sie von 32-Bit-Python das virtuelle "SysNative" -Verzeichnis verwenden. Zum Beispiel:

import os 
import platform 
import subprocess 

is32bit = (platform.architecture()[0] == '32bit') 
system32 = os.path.join(os.environ['SystemRoot'], 
         'SysNative' if is32bit else 'System32') 
bash = os.path.join(system32, 'bash.exe') 

subprocess.check_call('"%s" -c "echo \'hello world\'"' % bash) 

Hinweis, die derzeit Windows-Rohre nicht zu WSL Rohren überbrücken, so dass, wenn Sie versuchen, stdout=PIPE oder subprocess.check_output zu verwenden, wird der WSL bash loader scheitern. Sie könnten die Konsolenausgabe direkt über ReadConsoleOutputCharacter lesen (siehe z. B. this answer). Oder Sie können die Ausgabe einfacher in eine temporäre Datei umleiten, indem Sie den Pfad der temporären Datei als WSL-Pfad übergeben. Zum Beispiel:

import tempfile 

def wintolin(path): 
    path = os.path.abspath(path) 
    if path[1:2] == ':': 
     drive = path[:1].lower() 
     return '/mnt/' + drive + path[2:].replace('\\', '/') 

cmd = '"%s" -c "echo \'hello world\' > \'%s\'"' 

with tempfile.NamedTemporaryFile(mode='r', encoding='utf-8') as f: 
    subprocess.check_call(cmd % (bash, wintolin(f.name))) 
    out = f.read() 

Edit: Ab Windows 14951 bauen, sollten Sie in der Lage sein stdout=PIPE zu verwenden. Sehen Sie den WSL-Blogeintrag Windows and Ubuntu Interoperability.

Verwandte Themen