我有一个程序可以从另一个程序中获取输出,该程序在 linux 的新 Windows 子系统上运行。我已经编写了一个从 windows 系统运行的 python 程序,但将使用 python 子进程模块执行 linux 程序。如果这令人困惑,请参阅下面的示例。
但是,当我这样做时,我发现当通过 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
编辑:我意识到我的命令可能会出现问题,因为 o 在空间上 split 并且“echo hello world”是一个参数,但是用 bash -c ls
尝试同样的事情也会给出同样的错误
最佳答案
对于在 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=PIPE
或 subprocess.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 build 14951 开始,您应该能够使用 stdout=PIPE
。请参阅 WSL 博客文章 Windows and Ubuntu Interoperability .
关于python subprocess.call() 找不到 Windows Bash.exe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39812882/