我想在我的主python程序中使用subprocess打开一个Python脚本。我希望这两个程序能够互相聊天,因为它们都在运行,所以我可以监视从属脚本中的活动,即我需要它们在彼此之间发送字符串。
主程序将具有与此类似的功能,它将与从属脚本通信并进行监视:
脚本1
import subprocess
import pickle
import sys
import time
import os
def communicate(clock_speed, channel_number, frequency):
p = subprocess.Popen(['C:\\Python27\\pythonw','test.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
data = pickle.dumps([clock_speed, channel_number, frequency]).replace("\n", "\\()")
print data
p.stdin.write("Start\n")
print p.stdout.read()
p.stdin.write(data + "\n")
p.poll()
print p.stdout.readline()
print "return:" + p.stdout.readline()
#p.kill()
if __name__ == '__main__':
print "GO"
communicate(clock_speed = 400, channel_number = 0, frequency = 5*1e6)
test.py脚本与此类似:
脚本2
import ctypes
import pickle
import time
import sys
start = raw_input("")
sys.stdout.write("Ready For Data")
data = raw_input("")
data = pickle.loads(data.replace("\\()", "\n"))
sys.stdout.write(str(data))
###BUNCH OF OTHER STUFF###
我希望这些脚本执行的操作如下:
主要问题是如何做2-4部分。然后应该遵循两个脚本之间的其余通信。截至目前,我只能在脚本2终止后才能读取它。
非常感谢任何帮助。
更新
脚本1必须使用32位Python运行,而脚本2必须使用64位Python运行。
答案 0 :(得分:4)
管道的问题在于,如果您调用读取操作并且没有任何内容可读,则代码会停止,直到另一方写入您要阅读的内容为止。此外,如果你写得太多,你的下一个写操作可能会阻塞,直到另一方从管道读取内容并释放它。
您可以进行“非阻塞调用”,在这些情况下会返回错误而不是阻止,但您的应用程序仍然需要明智地处理错误。
无论如何,您需要设置某种协议。想想HTTP或你熟悉的任何其他协议:有请求和响应,当你正在阅读这两个协议中的任何一个时,协议总是会告诉你是否还有其他需要阅读的内容。这样你就可以随时决定是否等待更多数据。
这是一个有效的例子。它的工作原理是因为有以下协议:
为了在管道上写一条线(在任一侧)并确保它进入管道,我拨打write()
然后flush()
。
为了从管道中读取一行(在任一侧)而不是单个字节,从而阻止我的代码,直到该行准备好并且不再长于该行,我使用readline()
。
您可以进行其他调用以及其他协议,包括现成的协议,但单线协议适用于简单的事情以及类似的演示。
p1.py:
import subprocess
p = subprocess.Popen(['python', 'p2.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write("Hello\n")
p.stdin.flush()
print 'got', p.stdout.readline().strip()
p.stdin.write("How are you?\n")
p.stdin.flush()
print 'got', p.stdout.readline().strip()
p2.py:
import sys
data = sys.stdin.readline()
sys.stdout.write("Hm.\n")
sys.stdout.flush()
data = sys.stdin.readline()
sys.stdout.write("Whatever.\n")
sys.stdout.flush()
答案 1 :(得分:0)
我也遇到了类似的问题,在这种情况下,没有办法在不同进程之间发送通用Python对象,而没有遇到知道对方何时没有发送对象或被关闭的问题。同样尝试使用multiprocessing.Queue
通常意味着该过程需要由当前进程启动,而当两个进程想要协作时并非总是如此。
为了解决这个问题,我使用了picklepipe
模块,它定义了一个通用对象序列化管道接口以及一个使用pickle
协议PicklePipe
的管道(也是一个使用的名为MarshalPipe
的{{3}}协议。它可以发送的不仅仅是字符串,它可以将任何pickleable对象发送给它的同行。
管道甚至可以选择,这意味着当准备好接收新对象时,selectors
模块(或selectors2
,selectors34
)可以将它们用作文件对象。这使得等待许多不同的管道非常有效。
支持Python 2.7+(可能是2.6)和所有主要平台。甚至可以在两个不同版本的Python之间发送对象!查看marshal
或project documentation。
披露:我是picklepipe
的作者。我很想听听你的反馈。 :)