Python 进程间通信

3 投票
3 回答
3606 浏览
提问于 2025-04-16 11:23

我有一个用Python写的应用程序(带有图形界面,使用的是PyQt4),用户可以同时打开多个实例。这个应用程序用来执行一些需要很长时间的任务(可能需要几个小时到几天),所以我想加一个额外的“监控”应用程序,来做一些事情,比如:

  • 找到所有正在运行的其他应用程序的进程
  • 获取正在进行的操作的状态(比如完成的工作、进度百分比、错误信息等)
  • 有时向这些应用程序发送一些命令,比如让它们暂停、恢复或停止等

我想到的一个合适的方式是使用RPyC,但唯一的问题是,它似乎只能通过TCP套接字工作,就像我找到的大多数RPC库一样。这就导致需要打开几个不必要的套接字,只在本地监听,还得创建某种端口分配机制,以避免两个进程试图在同一个端口上监听。然后监控程序需要有一个端口列表,要么写在某个地方,要么去找正在监听TCP端口的进程,试图判断它们是否是正确应用的实例。这听起来有点麻烦。

我目前想到的管理进程间通信的最好方法是使用一些Unix套接字,比如放在'/var/run/myapp/myapp-.sock',然后创建一个模块来处理这些繁琐的事情,提供一些方法,比如listMyApps()getMyApp(pid),第一个返回一个进程ID的列表,第二个返回一个可以用来与那个应用程序通信的对象。

现在,我在寻找实现这个目标的最佳方法……真的没有现成的东西可以用来通过Unix套接字管理RPC吗?这让我觉得有点奇怪,但我找不到任何合适的东西……

有什么建议吗?

注意:我不想反向操作(应用程序是单一监控服务器的客户端),以避免监控应用崩溃时出现问题,并且让我可以自由创建其他连接到这些套接字并发出请求的应用程序。

注意:安全性不是问题,因为这些东西都在一个私有、封闭且有防火墙的网络中运行 :),而且请求都是由可信用户在本地发出的。

3 个回答

2

另一种方法是建立一个工作控制系统。这样,应用程序就不需要自己启动进程,而是可以注册一些任务来执行。然后,工作控制系统会监控这些已经启动的任务。这个设计的一个好处是,未来你可以把工作分散到很多台机器上去做。

2

但是这样会导致需要打开几个不必要的套接字,这些套接字只在本地监听,并且还需要创建某种端口分配机制,以避免两个进程试图监听同一个端口。

其实不是这样的。首先,大多数进程间通信都是通过套接字来实现的。可以是TCP套接字,也可以是UNIX套接字。你在使用标准输出和其他方式进行数据传输时,基本上就是在做这样的事情。

你也可以使用操作系统的信号。不过要注意,只有每个进程的主线程可以处理信号,所以你得小心不要让它被阻塞。

无论你用什么方法,基本上都绕不开使用套接字连接。

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]

如果有人感兴趣,告诉我一声,我可以分享一些代码示例或更多细节。

撰写回答