Python进程间通信

3
我有一个Python应用程序(带有GUI,使用PyQt4),用户可以生成多个实例。该应用程序用于执行一些长时间运行的任务(大约需要几小时到几天),因此我愿意添加一个额外的“监视”应用程序,它将执行以下操作:
- 查找其他应用程序的所有运行进程 - 获取正在运行的操作的状态(已完成的作业、百分比、错误消息等) - 最终向应用程序发送一些命令,告诉它们暂停、恢复、停止等。
适合此工作的一种方法是RPyC,唯一的问题是,它似乎只能在TCP套接字上工作,就像我发现的大多数RPC库一样。但这导致必须打开几个不必要的套接字,仅侦听本地主机,并且必须创建某种端口分配机制,以避免两个进程尝试侦听相同的端口。然后监视器需要在某处编写端口列表,或者查找侦听TCP端口并尝试确定它们是否为正确应用程序的实例。听起来很混乱。
我目前能想到的管理互相通信的最好方式是使用一些Unix套接字,假设在'/var/run/myapp/myapp-.sock'中,并创建一个模块来完成所有工作,公开一些方法,如listMyApps()getMyApp(pid),分别返回pid列表和可用于与该应用程序通信的对象。
现在,我正在寻找最佳方法来实现它。 真的没有已经完成的管理Unix套接字上RPC的东西吗?对我来说听起来有点奇怪,但我找不到任何适合的东西..
有什么建议吗?
注意:我不想颠倒事情(应用程序是单个监视服务器的客户端),以避免在监视应用程序崩溃时出现问题,并让我自由地创建其他连接到这些套接字并发出请求的应用程序。
注意:安全性不是问题,因为所有这些都在私有、封闭和防火墙网络中运行 :),此外,只有受信任的用户在本地主机上进行请求。
3个回答

2
我想我已经找到了一个解决方案,使用dbus-python。我能够将其与Qt4主循环集成,虽然在网站上他们说只支持glib(我猜这个页面没有更新)。我进行了快速测试,似乎工作得很好(我只是在名为com.example.myapp.<pid>的总线上公开了一些虚拟函数,并列出了实例并从外部客户端连接)。
然后,我可以仅通过TCP使用RPyC内容进行“主”控制应用程序和“管理器”应用程序之间的通信,后者在机器上的实例之间扮演“开关”的角色。
一些ASCII艺术澄清:
+-------------------+                    
| MASTER APP        |                    +--------------------+
| on my workstation |------ RPyC --------| Server#0 Manager   |
+-------------------+                    +--------------------+
      |                                      | | |
    RPyC                                     | | '-- dbus ---[INSTANCE #0]
      |                                      | '--- dbus ---[INSTANCE #1]
   +--------------------+                    '---- dbus ---[INSTANCE #2]
   | Server#1 Manager   |
   +--------------------+
      | | |
      | | '-- dbus ---[INSTANCE #0]
      | '--- dbus ---[INSTANCE #1]
      '---- dbus ---[INSTANCE #2]

如果有人感兴趣,请告诉我,我会发布一些代码示例/更多细节。

顺便说一下,S.O.使用的等宽字体根本不是等宽的,还是只有我这样觉得?ASCII艺术看起来很丑.. :( - redShadow
1
我现在正面临着完全相同的困境——多个长时间运行的进程独立生成,需要偶尔进行用户控制(停止、启动等)。这个答案是在'11年写的。你现在还会推荐dbus解决方案吗? - Lee Netherton

2

但这会导致需要打开几个不必要的套接字,只侦听本地主机,并且需要创建某种端口分配机制,以避免两个进程尝试侦听相同的端口。

不完全正确。首先,大多数进程间通信都是通过套接字进行的。可以使用TCP套接字或UNIX套接字。这基本上(不是完全)就是在管道标准输出等时所做的操作。

您还可以使用操作系统信号。虽然您必须记住,每个进程的主线程才能进行信号处理,因此必须小心不要阻塞该线程。

但无论您如何处理,几乎不可避免地需要使用套接字连接。


我的意思是,我不想为每个进程设置不同端口上的侦听套接字。我考虑了信号,但它们绝对不能满足我的需求,因为我需要运行各种应用程序函数的方法来查询其状态(不仅仅是完成百分比,而是更复杂的细节),或者执行一堆操作“就像用户点击了XYZ UI按钮”一样。 - redShadow

2
另一种方法是采用某种作业控制系统,而不是让应用程序启动自己的进程,而是注册要执行任务的作业。然后作业控制系统将监视已启动的作业。此设计的额外好处是,将来可以在多台机器上分散工作负载。

是的,这是一个好答案。看一下Python的多进程库。 - Falmarri
你对“作业控制系统”有什么建议?旧版本的应用程序只是生成了几个主应用程序线程(使用Python很容易处理),并且能够与它们通信,但我放弃了这种方式,因为如果出现操作失败或卡住、应用程序本身存在错误等情况时,拥有单独的进程更加方便,并且在某些情况下甚至可以通过STOP/CONT暂停/恢复进程。 - redShadow
1
你应该看看 multiprocessing 库。那里有一些很好的例子可以指导你。 - Falmarri
哦,我没意识到实际上有一个名为“multiprocessing”的库,它是Python标准模块中从未尝试过的之一.. :) 看起来很不错,尽管乍一看似乎需要进行太多的重构才能将其集成到我的现有应用程序中.. 这就是为什么我想到了在Unix套接字上进行RPC.. - redShadow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接