关于子进程:在python命令行上输入python命令

Input python commands on the python command line

这个标题可能令人困惑,但基本上我希望能够做到以下几点:

1
2
3
4
5
6
import subprocess

subprocess.call(["python"])
subprocess.call(["import","antigravity"])
subprocess.check_call(["print",""This is so meta""])
subprocess.call(["exit()"])

预期的行为是打开一个python终端会话,然后打开xkcd comic 353,在命令行中打印"this is so meta",最后退出python命令行。

基本上,我希望能够打开一个Python会话,并从我的Python脚本运行其中的命令。我还希望能够检查我在脚本中运行的命令的输出。这有可能吗?如果是这样,我需要使用什么库?子流程会这样做吗?


如果你需要与过程沟通,你应该使用communicate()方法,而不是stdin.write(),否则你会发现一些不理想的效果。

Warning Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

来源:http://docs.python.org/2/library/subprocess.html popen objects

1
2
3
4
5
6
7
8
9
10
11
12
from subprocess import PIPE, STDOUT, Popen

e = Popen(["/usr/local/bin/python3"], stdout = PIPE, stdin = PIPE, stderr = STDOUT, shell = False)

out, err = e.communicate(b"""
import sys
print('Interactive python version: %s' % str(sys.version))
sys.exit(4)
"""
)
e.wait()
print ('Exit code', e.returncode)
print ('Output', out)


您还可以使用代码模块:

1
2
3
4
import code
console = code.InteractiveConsole()
console.push('import antigravity')
console.push('print"something"')

如果出于某种原因,您希望在子进程中运行此模块,那么可以使用多处理模块:

1
2
3
4
5
6
7
8
9
10
11
12
import code
import multiprocessing as mp

def work():
    console = code.InteractiveConsole()
    console.push('import antigravity')
    console.push('print"something"')

if __name__ == '__main__':    
    proc = mp.Process(target=work)
    proc.start()
    proc.join()

要将stdout重定向到变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import code
import sys

class MyStream(object):
    def __init__(self, target):
        self.target = target
        self.value = None
    def write(self, s):
        if s.strip():
            self.value = s

sys.stdout = stream = MyStream(sys.stdout)
console = code.InteractiveConsole(locals=locals())
console.push('import antigravity')
console.push('print"something"')
sys.__stdout__.write('output: {}
'
.format(stream.value))

印刷品

1
output: something

请注意,consolesys.stdout已重定向到MyStream(sys.stdout)。它不打印任何内容,但将最后一个字符串存储在self.value中。要打印到字符串,可以使用sys.__stdout__.write(注意下划线)。


像这样的…

1
2
3
4
5
6
7
8
9
10
11
import subprocess
proc = subprocess.Popen(
    'python',stdout=subprocess.PIPE,
    stdin=subprocess.PIPE)
proc.stdin.write('import antigravity
'
)
proc.stdin.write('print"something"
'
)
proc.stdin.close()
result = proc.stdout.read()
print result

所以我们创建了一个进程,告诉它输入将来自stdin(比如有人输入)。然后,我们编写任何我们喜欢的内容,并读取stdout的响应(通常打印到屏幕上的内容)