C应用程序和Python之间的IPC

时间:2015-12-16 15:08:11

标签: python c ipc

所以我对IPC比较陌生,我有一个收集数据的c程序和一个分析数据的python程序。我希望能够:

  1. 将python程序作为主c程序的子进程调用
  2. 将包含要处理的数据的c结构传递给python进程
  3. 将python进程中的int值返回给c程序
  4. 我一直在简短地查看Pipes和FIFO,但到目前为止找不到任何信息来解决这类问题,因为据我所知,fork()例如只会复制调用进程,所以不是我的希望因为我试图称之为不同的过程。

4 个答案:

答案 0 :(得分:3)

关于 fork() 以及执行其他流程的必要性。确实fork()创建了当前进程的副本。但这通常与exec()(各种形式之一)相结合,以使进程副本执行不同的程序。

对于 IPC ,您有多种选择。有人提到了一个队列 - 但像ZeroMQ这样的东西太过分了。您可以使用以下几种机制之一来IPC

  1. Pipes(命名管道或匿名)
  2. Unix域套接字
  3. TCPUDP通过套接字API
  4. Shared memory
  5. Message queues
  6. pipe方法最简单。请注意,当您在C程序和Python之间来回传递数据时,您需要担心数据的传输语法。如果选择使用C结构(可以是非可移植的),则需要在Python端解包数据。否则,您可以使用某种文本格式 - sprintf / sscanfJSON等的组合。

答案 1 :(得分:2)

我建议查看应用程序并构建您遇到的问题。

多线程

到目前为止,启动两个流程并不是最大的问题,因为Ziffusion说你可以让另一个流程做其他事情。另外还有C语言的python绑定,所以你可以创建另一个例子(不需要它成为一个进程)并从C程序中调用你的python例程。

通信

共享信息更有趣,因为您必须解决两个问题:一个是从技术上将数据从一个地方转移到另一个地方而反之亦然;另一个是两个不同的东西如何对同一数据起作用。 这涉及消息传递模式和流程:

  • 谁生成数据?
  • 谁收到数据?
  • 在继续之前是否有一段代码等待某事?
  • 是否需要控制处理数据时数据会发生什么?
  • 我想自己编码吗?
  • 我可以在项目中使用库吗?
  • 有安全限制吗?
  • ...

回答上述问题后,您可以定义应用程序的各个部分的交互方式。一个主要区别是同步与异步。

同步与异步

同步意味着每个消息都有一个回复,应该包含在有限(通常尽可能小)的大小的时间包络中。这是为了避免延迟。 当您必须精确控制正在发生的事情时,或者您需要及时回答 问题时,最好使用这种模式。 事实上,http是如何下载网页的:无论何时加载网站,您都希望立即看到内容。 这是一种名为 REQ uest / REP ly

的模式

异步通常用于处理繁重的情况:数据生成器(例如数据库接口或传感器)将大量数据发送到工作线程,而不等待答案。然后,工作线程开始对数据执行任务,完成后将结果发送到数据接收器/用户。 此模式称为 PUB lish / SUB 划线。

还有很多其他的,但这些构成了沟通的基础。

编组

您面临的另一个问题是如何构建数据传递,编组。 如何将数据的含义和内容从一个上下文转换为完全不同的上下文。 例如,从你的C部分到你的Python部分。 维护序列化库是繁琐且危险的,更不用说容易出现向后兼容性问题了。

实施

当您实现时,您通常需要最干净,最强大的代码。这两件事显然是相互对立的。所以我通常会去寻找能够完全满足我需要的库。 在这种情况下,我的建议是尝试ZeroMQ:它很薄,灵活,低级。 它将为您提供一个强大的框架来连接线程,进程甚至机器。 ZeroMQ提供链接,但您仍需要通过此链接运行协议。 为了避免令人难以置信的麻烦并简化您关于编组问题的工作,我建议您调查可用的编组库,以简化此任务。 Cap'n protoFlatbuffers,协议缓冲区(Google,尚未发布超过2个链接) 它们可以很容易地用中间语言定义数据,并用任何其他语言对其进行解析,而无需自己编写所有类。

至于管道和共享记忆,我的拙见是:忘记它们的存在。

答案 2 :(得分:0)

您组织架构的方式有点混乱。你真正想要的是Message Queues。所以在你的例子中:

  • 您的python worker侦听要在队列A中处理的新信息;
  • 您的C程序在队列A中输入数据;
  • 您的python worker处理数据并将结果排入队列B;
  • 您的C程序侦听队列B上的新项目;

这可能会有所不同,但概念很简单。

它们易于实施,并且有大量的库和工具可以帮助您完成此任务。 ZeroMQ肯定会为你做的。它适用于C和Python。

答案 3 :(得分:0)

如果你的结构很简单,你根本就不能使用IPC。提供,您可以序列化它作为可用作程序参数的字符串参数,并提供返回的int值可以在0-127范围内,您可以简单地:

    C代码中的
    • 准备要传递给Python脚本的命令参数
    • fork-exec(假设类Unix系统)带有脚本路径和脚本参数的Python解释器
    • 等待终止孩子
    • 读取脚本作为代码终止传递的内容
  • Python中的
    • 从命令行获取参数并重建struct
    • 的元素
    • 处理它
    • exit(n)结束脚本,其中n是0-127范围内的整数,将返回给调用者。

如果以上不符合您的要求,下一级将是使用管道:

    C代码中的
    • 准备2个管道对,一个用于C-> Python(让我们称之为输入),一个用于Python-> C(让我们称之为输出)
    • 将结构序列化为char缓冲区
    • 在孩子身上
      • 关闭输入管道的写入侧
      • 输出管道的关闭读取侧
      • 读取输入管道的一侧到文件描述符0(stdin)(参见`dup2)
      • 将输出管道的一侧写入文件描述符1(stdout)
      • 执行带有脚本名称的Python解释器
    • 父母中的
      • 输入管道的关闭读取侧
      • 关闭输出管道的写入侧
      • 在输入文件的写入端写入缓冲区(最后以其大小,如果不能先验地知道)
      • 等待孩子终止
      • 从输出管道的读取端读取返回值
  • Python中的
    • 从标准输入中读取序列化数据
    • 处理它
    • 将输出整数写入标准输出
    • 出口