从python与bash交互

jus*_*nas 14 python bash subprocess

我一直在玩Python的subprocess模块,我想用python的bash做一个"交互式会话".我希望能够像在终端仿真器上一样从Python读取bash输出/写入命令.我猜一个代码示例更好地解释了它:

>>> proc = subprocess.Popen(['/bin/bash'])
>>> proc.communicate()
('user@machine:~/','')
>>> proc.communicate('ls\n')
('file1 file2 file3','')
Run Code Online (Sandbox Code Playgroud)

(显然,它不会那样工作.)这样的事情是可能的,怎么样?

非常感谢

Ada*_*dam 11

试试这个例子:

import subprocess

proc = subprocess.Popen(['/bin/bash'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
stdout = proc.communicate('ls -lash')

print stdout
Run Code Online (Sandbox Code Playgroud)

你必须阅读更多关于stdin,stdout和stderr的信息.这看起来很好的讲座:http://www.doughellmann.com/PyMOTW/subprocess/

编辑:

另一个例子:

>>> process = subprocess.Popen(['/bin/bash'], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> process.stdin.write('echo it works!\n')
>>> process.stdout.readline()
'it works!\n'
>>> process.stdin.write('date\n')
>>> process.stdout.readline()
'wto, 13 mar 2012, 17:25:35 CET\n'
>>> 
Run Code Online (Sandbox Code Playgroud)

  • 第一个.communicate()调用工作良好,但是如果我尝试再次通信,则会发生这种情况:“ ValueError:对关闭文件的I / O操作”。有什么办法可以使其继续运行吗? (2认同)
  • 您的“另一个示例”在Python3.5中不起作用。有什么办法解决吗? (2认同)
  • @waitingkuo是因为在Python 3中,`buffsize`的默认值为-1,在2中的默认值为0,因此在Popen中将其设置为0即可使用。对我来说确实如此。 (2认同)

小智 6

这应该是你想要的

    import subprocess
    import threading
    
    p = subprocess.Popen(["bash"], stderr=subprocess.PIPE,shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    exit = False
    
    def read_stdout():
        while not exit:
            msg = p.stdout.readline()
            print("stdout: ", msg.decode())
    def read_stderro():
        while not exit:
            msg = p.stderr.readline()
            print("stderr: ", msg.decode())
    
    threading.Thread(target=read_stdout).start()
    threading.Thread(target=read_stderro).start()
    
    while not exit:
        res = input(">")
        p.stdin.write((res + '\n').encode())
        p.stdin.flush()
Run Code Online (Sandbox Code Playgroud)

测试结果:

>ls
>stdout:  1.py

stdout:  2.py

ssss
>stderr:  bash: line 2: ssss: command not found
Run Code Online (Sandbox Code Playgroud)