Python: 将GUI进程与核心逻辑进程分离

13 投票
5 回答
3744 浏览
提问于 2025-04-15 17:21

我正在开发一个用于计算机模拟的 Python项目,同时也在为它制作一个图形用户界面(GUI)。其实,核心逻辑本身并不需要图形界面。为了制作这个界面,我使用的是wxPython,但我觉得我的问题比较普遍,不仅仅依赖于这个工具。

目前,图形界面的工作方式是,它和核心逻辑包(叫做 garlicsim)在同一个进程和同一个线程里运行。这种方式可以工作,但我知道这样做有问题,因为如果核心逻辑需要进行一些复杂的计算,图形界面就会卡住,这让我觉得不可接受。

那我该怎么办呢?

我听说可以把核心逻辑放在一个和图形界面不同的进程里运行。这听起来很有趣,但我对此有很多疑问。

  1. 我应该使用 multiprocessing 包还是 subprocess 包来启动新的进程呢?
  2. 我怎么才能方便地从图形界面访问模拟数据呢?毕竟,这些数据会存储在另一个进程里。用户应该能够轻松流畅地浏览模拟的时间线。这该怎么实现呢?

5 个回答

2

这里最简单的方法就是在一个单独的线程中启动计算,然后通过Queue对象在这个线程和图形界面(GUI)之间传递数据。这样做是非常安全的,而且在不同线程之间交流数据也很方便。

其他的解决方案就比较复杂了——你可能需要在一个完全独立的“服务器”进程中运行模拟,然后通过套接字与主图形界面进行通信。

2

来回答具体的问题。

“我应该使用 multiprocessing 包还是 subprocess 包来启动新进程?”

multiprocessing

“我怎么才能方便地从图形界面(GUI)访问模拟数据?”

如果你是问能不能直接访问模拟进程的对象,那是不行的。模拟是一个独立的进程。你可以启动它、停止它,最重要的是,可以通过一个命令队列向模拟器发送请求。

“用户应该能够轻松流畅地浏览模拟的时间线。这怎么实现?”

这只是设计问题。单进程、多进程或多线程对这个问题没有影响。

每个模拟都必须有一些参数,它必须启动,并且必须生成一个日志(或时间线)。无论你使用什么库来启动和停止模拟,这一点都是必须的。

模拟的输出——也就是你图形界面的输入——可以有很多种方式来实现。

  • 数据库。模拟的时间线可以插入到一个 SQLite 数据库中,然后由图形界面查询。这种方法效果不是特别好,因为 SQLite 的锁机制不是很聪明,但还是能用。

  • 文件。模拟的时间线写入一个文件,图形界面读取这个文件。这种方法效果非常好。

  • 请求/回复。模拟有多个线程,其中一个线程负责处理命令并回复,比如发送当前的时间线,或者停止模拟,或者更改参数并重新启动。

6

你可以在这里找到一些灵感:http://wiki.wxpython.org/LongRunningTasks,不过这个是关于多线程的,不是多进程的。

基本思路

  • 对于多线程:可以用事件队列来让图形界面(GUI)和处理线程之间进行沟通。
  • 对于多进程:可以考虑使用 subprocess 这个包,通过子进程的 stdin/stdout 来和它交流。这样你需要一个命令行的接口,但这最终会很有用,因为你可以进行不依赖于图形界面的单元测试。

你甚至可以通过一个套接字来进行输入输出的通信,这样可以方便地管理模拟的网络。

编辑:我刚看到你提到的2.6新版本的 multiprocessing 包。看起来不错,你可以用队列在进程之间进行沟通。这种方式联系更紧密,你可以根据自己的需求来选择。

撰写回答