3

我想在我的主 python 程序中使用子进程打开一个 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###

我希望这些脚本执行以下操作:

  1. 脚本 1 使用 Popen 打开脚本 2
  2. 脚本 1 发送字符串“Start\n”
  3. 脚本 2 读取此字符串并发送字符串“Ready For Data”
  4. 脚本 1 读取此字符串并将腌制数据发送到脚本 2
  5. 然后随便...

主要问题是如何执行第 2-4 部分。然后应该遵循两个脚本之间的其余通信。到目前为止,我只能在脚本 2 终止后读取字符串。

任何帮助是极大的赞赏。

更新:

脚本 1 必须使用 32 位 Python 运行,而脚本 2 必须使用 64 位 Python 运行。

4

2 回答 2

4

管道的问题是,如果你调用了一个读操作并且没有什么要读的,你的代码就会停滞不前,直到对方写了一些东西给你读。此外,如果你写得太多,你的下一个写操作可能会阻塞,直到对方从管道中读取一些东西并释放它。

您可以进行“非阻塞调用”,在这些情况下将返回错误而不是阻塞,但您的应用程序仍需要明智地处理错误。

无论如何,您需要设置某种协议。想想 HTTP 或您熟悉的任何其他协议:有请求和响应,当您阅读两者中的任何一个时,协议总是会告诉您是否需要阅读其他内容。这样,您始终可以就是否等待更多数据做出明智的决定。

这是一个有效的示例。它之所以有效,是因为有以下协议:

  • p1 发送一行,以 '\n' 结尾;
  • p2 做同样的事情;
  • p1 发送另一行;
  • p2 做同样的事情;
  • 两人都很高兴并退出。

为了向管道(在任一侧)写入一行并确保它进入管道,我调用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()
于 2013-03-14T01:41:15.560 回答
0

我也遇到了类似的问题,没有办法在不同进程之间发送通用 Python 对象,而不会遇到知道对方何时没有发送对象或关闭的问题。还尝试使用multiprocessing.Queue通常意味着该进程需要由当前进程启动,这在两个进程想要协作时并不总是如此。

为了解决这个问题,我使用了该picklepipe模块,它定义了一个通用对象序列化管道接口以及一个使用pickle名为 the的协议的管道PicklePipe(也使用marshal名为 的协议MarshalPipe)。它不仅可以发送字符串,还可以将任何可腌制对象发送给它的对等方。

管道甚至是可选择的,这意味着当准备接收新对象时,selectors模块(或selectors2, )可以将它们用作文件对象。selectors34这使得等待许多不同的管道准备好非常有效。

支持 Python 2.7+(可能还有 2.6)和所有主要平台。甚至可以在两个不同版本的 Python 之间发送对象!查看项目文档查看 Github 上的源代码

披露:我是picklepipe. 我很想听听您的反馈。:)

于 2016-12-29T17:15:24.960 回答