我有一个程序从另一个程序获取输出,该程序在新的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
编辑:我意识到我的命令可能会产生问题,因为我正在拆分空间和&#34;回声问候世界&#34;是一个参数,但使用bash -c ls
尝试相同的操作也会产生相同的错误
答案 0 :(得分:4)
对于在WOW64子系统中运行的32位程序,&#34; System32&#34;目录gets redirected到&#34; SysWOW64&#34;。 WSL bash.exe加载程序作为64位可执行文件分发,因此从32位Python开始,您需要使用虚拟&#34; SysNative&#34;目录。例如:
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版本14951开始,您应该可以使用stdout=PIPE
。请参阅WSL博客文章Windows and Ubuntu Interoperability。