使用Python的子进程模块将Python解释器作为子进程运行时遇到问题

时间:2014-12-21 17:40:54

标签: python python-2.7 subprocess

我正在尝试理解Python的子进程模块是如何工作的,并且已经开始为自己设置一些不像我想象的那么简单的问题。具体来说,我正在尝试与作为子进程创建的Python解释器进行交互。

我已经创建了一个测试模块dummy.py,其结构如下:

def hi():
    print "Hi Earth"


hi()

然后,为了测试我使用子进程模块的能力,我编写了一个名为pyrun.py的模块,其结构如下:

import subprocess

def subprocess_cmd1():
    outFile = open("tempy1.tmp",'w')
    proc = subprocess.Popen("pwd", stdin=subprocess.PIPE, stdout=outFile, stderr=outFile, shell=True)
    outFile.close()

def subprocess_cmd2():
    outFile = open("tempy2.tmp",'w')
    proc = subprocess.Popen('python dummy.py', stdin=subprocess.PIPE, stdout=outFile, stderr=outFile, shell=True)
    outFile.close()

def subprocess_cmd3():
    outFile = open("tempy3.tmp",'w')
    proc = subprocess.Popen('python', stdin=subprocess.PIPE, stdout=outFile, stderr=outFile, shell=True)
    proc.communicate('import dummy')
    outFile.close()

def subprocess_cmd4():
    outFile = open("tempy4.tmp",'w')
    proc = subprocess.Popen('python', stdin=subprocess.PIPE, stdout=outFile, stderr=outFile, shell=True)
    proc.communicate('import dummy')
    proc.communicate('dummy.hi()')
    outFile.close()

print "Start"
subprocess_cmd1()
subprocess_cmd2()
subprocess_cmd3()
subprocess_cmd4()
print "Stop"

这个想法是从调用进程向子进程发送输入,并将所有输出发送到文本文件。

当我尝试从命令行运行pyrun时,我得到以下结果:

me@Bedrock1:~/Projects/LushProjects/newCode$ python pyrun.py
Start
Traceback (most recent call last):
  File "pyrun.py", line 42, in <module>
    subprocess_cmd4()
  File "pyrun.py", line 35, in subprocess_cmd4
    proc.communicate('dummy.hi()')
  File "/usr/lib/python2.7/subprocess.py", line 785, in communicate
    self.stdin.write(input)
ValueError: I/O operation on closed file

subprocess_cmd1 - 3在没有崩溃的情况下运行。在尝试执行语句时,错误出现在subprocess_cmd4()中:

proc.communicate('dummy.hi()')

这似乎是因为communicate方法在首次使用后将管道关闭到stdin。为什么这样做?假设管道应该关闭是否有任何好处?

另外,当我查看tempy3.tmpsubprocess_cmd3的输出文件)的内容时,它缺少Python解释器的“开始”文本 - 即

Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

为什么?我重定向了两个 stdout&amp; stderroutFile

最后,为什么tempy4.tmp完全为空?它至少应该包含在崩溃之前发送给它的文本吗? (即它应该看起来很像tempy3.tmp

3 个答案:

答案 0 :(得分:1)

问题在于你如何使用subprocess.communicate(),它需要一个字符串。来自文档

https://docs.python.org/2/library/subprocess.html

  

与流程交互:将数据发送到stdin。从stdout和。读取数据   stderr,直到达到文件结尾。等待进程终止。   可选的输入参数应该是要发送给子级的字符串   如果没有数据应该发送给孩子,则处理或无。

试试这个:

def subprocess_cmd4():
    outFile = open("tempy4.tmp",'w')
    proc = subprocess.Popen('python', stdin=subprocess.PIPE, stdout=outFile, stderr=outFile, shell=True)
    proc.communicate('import dummy\ndummy.hi()\n')
    outFile.close()

答案 1 :(得分:1)

定义你的翻译:

interpreter=sys.executable

并传递一个列表作为第一个参数:

fproc=subprocess.Popen([interpreter,script,'-f',datafile], stdout=subprocess.PIPE)

答案 2 :(得分:0)

回答有关communicate()

的问题

communicate()只能使用一次,因为在第一次通信后被调用的outFile已关闭。再次调用communicate()将永远不会产生任何结果,因为您已经读取了前一个中的所有输出。使用它的一个优点是您在使用它之后不需要终止。

回答您关于pythontempy3.py命令标题的位置的问题。

这只是python的标题,并不是一个回答&#39;问题&#39;。你只是进入python模式,而不是要求任何回复。 然而,如果您尝试:

proc.communicate('1+1')

那么应该将2写入文件tempy4.tmp,对吗?

即可。这是因为communicate()只能从Unix命令行输出,而不能从python输出。 e.g。

proc = subprocess.Popen('ls', stdin=subprocess.PIPE, stdout=outFile, stderr=outFile, shell=True)
proc.communicate('-l')

输出:

student@ubuntu:~/Desktop/Testing$ pg tempy4.tmp                                
dummy.py
dummy.pyc
pyrun.py
tempy1.tmp
tempy2.tmp
tempy3.tmp
tempy4.tmp

我按原样运行了您的程序,tempy4.tmp实际显示Hi Earth一次,并且您输入的错误相同。但是,如果你摆脱了第二个communicate()并只有一个,你就可以像@ user590028那样指出:

proc.communicate('import dummy\ndummy.hi()\n')

但是,子进程允许您使用stdin.write执行此操作,而不是将所有命令组合成一行:

proc.stdin.write('import dummy\n')
proc.communicate('dummy.hi()')

*确保在命令后面添加\n换新行。 他们都输出:

Hi Earth
Hi Earth