使用python脚本处理多个bash线程?

时间:2015-01-11 16:51:37

标签: python bash

我希望有一个python脚本,模拟用户有3个打开的终端窗口,并在每个窗口上并行调用命令。我设想它像:

cmd1 = Bash()
cmd1.call('cd python')
cmd2 = Bash()
cmd2.call('cd haskell')
cmd3 = Bash()
cmd3.call('cd rust')
for question in range(5):
   output1 = cmd1.call('python {}'.format(question))
   output2 = cmd1.call('./{}'.format(question))
   output3 = cmd1.call('./{}'.format(question))
   [format output and print stuff]

所以基础python脚本充当一种主管。我愿意为这项任务使用更好的工具。

1 个答案:

答案 0 :(得分:0)

Python 2的版本:

#!/usr/bin/env python
from subprocess import Popen, PIPE, STDOUT
from select     import select
from time       import sleep
from os         import read
cmd1 = Popen('bash', stdin=PIPE, stdout=PIPE, stderr=STDOUT, cwd='python')
cmd2 = Popen('bash', stdin=PIPE, stdout=PIPE, stderr=STDOUT, cwd='haskell')
cmd3 = Popen('bash', stdin=PIPE, stdout=PIPE, stderr=STDOUT, cwd='rust')
def gather_output(rlist, output):
    for reads in iter(lambda: select(rlist, [], [], 0)[0], []):
        for ready in reads:
            output[rlist.index(ready)] += read(ready.fileno(), 4096)
for question in range(5):
    cmd1.stdin.write('python {0}\n'.format(question))
    cmd2.stdin.write(     './{0}\n'.format(question))
    cmd3.stdin.write(     './{0}\n'.format(question))
cmdo = [cmd1.stdout, cmd2.stdout, cmd3.stdout]
output = [""]*len(cmdo)
while not output[2]:
    sleep(.1)
    gather_output(cmdo, output)
print 1, '\n', output[0]
print 2, '\n', output[1]
print 3, '\n', output[2]

函数gather_output(rlist, output)对于任务至关重要。它从rlist中的管道读取已经的命令输出,并将其连接到相应的output[]字符串。它不会阻塞,所以它可以在任何适合应用程序的时候调用,它依赖于它(如JF Sebastian在上面的评论中暗示的那样)何时停止读取输出 - 可能是在一定时间之后,或者当输出中出现某个字符串时。在这里的示例中,我偶然选择从命令收集输出,直到出现第三个命令的某些输出。关于os.read()的使用的注意事项:这比“文件对象”经常看到的read()或readline()方法更好用 - readline()不适用于非终止行,并且read(1)可能效率很低,在每个输出字节的基础管道上发出一个read()调用。最后,由于select使用了管道,这只适用于理智的操作系统,而不适用于Windows。

Python 3的变化:

            output[rlist.index(ready)] += read(ready.fileno(), 4096).decode()
...
    cmd1.stdin.write('python {0}\n'.format(question).encode())
    cmd2.stdin.write(     './{0}\n'.format(question).encode())
    cmd3.stdin.write(     './{0}\n'.format(question).encode())
...
print(1, output[0], sep='\n')
print(2, output[1], sep='\n')
print(3, output[2], sep='\n')