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

13
我正在开发一个用于处理计算机模拟的Python项目,同时也在为它开发GUI。(核心逻辑本身不需要GUI。)我使用的GUI工具包是wxPython,但我认为我的问题足够普遍,不依赖于它。
目前GUI的工作方式是,在同一进程和线程上启动核心逻辑包(称为garlicsim)。这种方法可行,但我知道它是有问题的,因为如果核心逻辑需要进行一些费时的计算,GUI将会挂起,这是不可接受的。
我该怎么办?
我听说过在GUI之外的单独进程中启动核心逻辑的选项。这听起来很有趣,但我对此有很多问题。
  1. 我应该使用multiprocessing包还是subprocess包来启动新进程?
  2. 如何轻松访问GUI进程中的模拟数据?毕竟,它将存储在其他进程中。用户应该能够轻松流畅地浏览模拟时间线。怎么做才能实现这一点?
5个回答

6
你可能会在这里找到一些灵感:http://wiki.wxpython.org/LongRunningTasks,但它是关于多线程的,而不是多进程。
基本思路:
- 对于多线程:使用事件队列在GUI和处理线程之间进行通信。 - 对于多进程:可以使用subprocess包,并使用子进程的stdin/stdout与其通信。为此,您需要一个命令行API,但最终它会变得方便,因为您可以进行独立于GUI的单元测试。 - 您甚至可以通过套接字来驱动i/o通信,这将使模拟的网络管理变得容易。 编辑:我刚看到你提到的2.6新的multiprocessing包。看起来不错,然后您可以使用队列在进程之间通信。这是更紧密的耦合,您可以根据自己的需求选择。

您说的“subprocessing”包应该是指“subprocess”包,对吗? - Kylotan

2
为了回答这些具体问题:
“我应该使用multiprocessing包还是subprocess包来启动新进程?”
使用multiprocessing。
“如何轻松顺畅地访问GUI进程中的模拟数据?”
如果您想问的是模拟过程对象的访问权限,那么您无法访问。模拟是一个单独的进程。您可以启动它、停止它,并通过命令队列向模拟器发送请求,这是最重要的。
“用户应该能够轻松流畅地浏览模拟的时间轴。如何做到这一点?”
这只是设计问题。单个进程、多个进程、多个线程对这个问题没有任何影响。
每个模拟都必须有一些参数,必须启动,必须产生日志(或时间轴)。无论您使用什么库来启动和停止模拟,都必须这样做。
模拟的输出(作为GUI的输入)可以用无数种方式完成。
- 数据库。模拟时间轴可以插入SQLite数据库并由GUI查询。这不是非常好的解决方案,因为SQLite没有真正聪明的锁定机制。但它确实可以工作。 - 文件。模拟时间轴写入文件。GUI读取文件。这非常好用。 - 请求/回复。模拟具有多个线程,其中一个线程正在出队命令并通过发送时间轴(例如)回复,或停止模拟或更改参数并重新启动。

2

在这里可行的最简单方法是在单独的线程中启动计算,并使用Queue对象在该线程和GUI之间通信。这些对象完全安全,非常方便进行线程间通信。

其他解决方案更为复杂 - 您可能最终会在一个完全独立的"服务器"进程中运行模拟,并通过套接字与主GUI进行通信。


1

不幸的是,即使您正确地选择了GUI不会影响答案,但解决此问题的最佳方法取决于模拟数据正在做什么。

例如,如果它生成顺序数据,则可以通过线程安全或进程安全队列将其提供给GUI。但是,如果它改变了整个数据且您的GUI需要能够随时查看快照,则通过将整个状态沿队列发送来解决可能过于昂贵,而可能需要使用互斥样式方法来共享访问数据结构。因此,在这里进行处理数据的工作性质至关重要。

至于是否使用多进程或子进程,这取决于是否有完全独立的程序处理数据。前者用于以多线程的方式进行多进程处理——同一程序的不同部分在多个进程中运行。后者是当一个程序想要运行另一个程序(可能是程序的副本,但通常不是)时。同样,很难知道哪种方法是针对您特定情况的最佳方法,尽管听起来您可以将核心逻辑作为命令行应用程序并通过管道、插座等进行通信。


0

使用多进程或Pyro进行分布式数据对象处理。

http://pyro.sourceforge.net/

你的模拟程序向GUI提供分布式对象,GUI对它们进行操作并读取它们的属性。

这两个库都可以在本地运行,并且提供了网络扩展性而无需麻烦。当你的模拟开始处理过多的数据时,可以添加更多的模拟服务器来提供更多的分布式对象。


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