2016-10-02 50 views
1

我有一個程序,從另一個程序運行在Linux的新的Windows子系統輸出。我已經編寫了一個從Windows系統運行的python程序,但會使用python subprocess模塊​​執行linux程序。如果這是令人困惑的,請參閱下面的示例。python subprocess.call()無法找到Windows Bash.exe

但是,當我這樣做時,我發現,通過python子進程調用時,Windows無法找到bash程序。

例如在Windows命令行或PowerShell的:

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 

我想,也許它不是以某種方式加載我的路徑設置,所以我把bash程序的詳細地址。

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

編輯:我知道,因爲在空間Ø上午分裂和我的命令可能被賦予的問題在「回聲世界你好」是一個說法,但試圖與bash -c ls同樣的事情也給出了同樣的錯誤

+0

@eryksun謝謝你,我知道bash只有64位,但並不認爲如果出現兼容性問題會導致這種類型的錯誤。我將只用64位版本的python來運行我的程序。請把這個作爲答案,以便我可以接受它! – jeffpkamp

+0

附註:'s.call('bash -c「echo hello world''。split())'_wrong_。你只需調用程序就好像'echo','hello'和'world''作爲三個獨立的參數傳遞。如果您絕對必須分割單個字符串文字,請使用像'shlex.split'這樣的函數來理解引用規則。 – ShadowRanger

回答

3

對於在WOW64子系統中運行的32位程序,將「System32」目錄gets redirected改爲「SysWOW64」。 WSL bash.exe加載程序以64位可執行文件的形式分發,因此從32位Python開始,您需要使用虛擬「SysNative」目錄。例如:

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) 

注意,目前Windows管道不橋接WSL管道,因此,如果您嘗試使用stdout=PIPEsubprocess.check_output,在WSL bash的裝載機將失敗。您可以通過ReadConsoleOutputCharacter直接讀取控制檯輸出(例如,請參閱this answer)。或者,更簡單地說,您可以將輸出重定向到臨時文件,將臨時文件的路徑作爲WSL路徑轉換。例如:

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

編輯:的Windows打造14951,你應該能夠使用stdout=PIPE。請參閱WSL博客文章Windows and Ubuntu Interoperability