Python:将GUI流程与核心逻辑流程分开

时间:2009-12-25 13:57:02

标签: python user-interface multiprocessing user-experience

我正在开发一个用于处理计算机模拟的Python project,我也在为它开发GUI。 (核心逻辑本身不需要GUI。)我使用的GUI工具包是wxPython,但我认为我的问题很普遍,不能依赖它。

GUI当前的工作方式是它在同一进程和GUI上启动核心逻辑包(称为garlicsim)。这是有效的,但我理解这是一个有问题的方法,因为如果核心逻辑需要做一些硬计算,GUI将挂起,我认为这是不可接受的。

我该怎么办?

我听说过在GUI的单独进程上启动核心逻辑的选项。这听起来很有趣,但我对此有很多疑问。

  1. 我是否使用multiprocessing包或subprocess包启动新流程?
  2. 如何从GUI流程轻松访问模拟数据?毕竟,它将存储在另一个进程中。用户应该能够轻松顺畅地浏览模拟的时间线。怎么办呢?

5 个答案:

答案 0 :(得分:6)

您可能会在这里找到一些灵感:http://wiki.wxpython.org/LongRunningTasks,但它适用于多线程,而不是多处理。

基本理念

  • 用于多线程:使用事件队列在GUI和处理线程之间进行通信。
  • 用于多处理:可以使用子进程包,并使用子进程的 stdin / stdout 与之通信。为此你需要一个命令行api,但它最终会派上用场,因为你可以进行gui独立的单元测试。

您甚至可以通过套接字驱动i / o通信,这样可以轻松进行模拟的网络管理。

编辑:我刚看到你提到的2.6新的多处理包。看起来不错,你可以使用队列在进程之间进行通信。这是一种更紧密的耦合,您可以根据自己的需要进行选择。

答案 1 :(得分:2)

回答具体问题。

“我是否使用multiprocessing软件包或subprocess软件包启动新流程?”

使用multiprocessing

“如何从GUI流程轻松访问模拟数据?”

您无权访问模拟过程对象,如果这就是您所要求的模拟是一个单独的过程。您可以启动它,停止它,并且 - 最重要的是 - 通过发送到模拟器的命令队列发出请求。

“用户应该能够轻松顺畅地浏览模拟的时间线。如何做到这一点?”

这只是设计。单个进程,多个进程,多个线程根本不会对这个问题产生任何影响。

每个模拟必须有一些参数,它必须启动,它必须产生一个日志(或时间轴)。无论您使用什么库来启动和停止模拟,都必须这样做。

模拟的输出 - 输入到GUI - 可以完成一百万次。

  • 数据库。可以将模拟时间轴插入到SQLite数据库中并由GUI查询。这不是很好,因为SQLite没有真正聪明的锁定。但它确实有效。

  • 文件。模拟时间线被写入文件。 GUI读取文件。这非常非常好。

  • 请求/回复。模拟有多个线程,其中一个是出队命令并通过 - 例如 - 将时间线发送回到当前时间,或停止模拟或更改参数并重新启动它来进行响应。

答案 2 :(得分:2)

这里最适合您的方法是在单独的线程中启动计算,并使用Queue对象在此线程和GUI之间传递数据。这些是完全安全的,非常便于线程间通信。

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

答案 3 :(得分:1)

不幸的是,尽管你选择GUI不会影响答案是对的,但解决这个问题的最佳方法很大程度上取决于你的模拟数据究竟在做什么。

例如,如果它生成顺序数据,那么它可以通过线程安全或进程安全的队列将其提供给GUI。但是,如果它改变整个数据并且您的GUI需要能够在任何给定时间看到快照,那么通过沿着队列发送整个状态来解决这个问题可能太昂贵,并且可能需要使用互斥式方法来共享访问权限到数据结构。因此,对您的数据所做工作的性质至关重要。

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

答案 4 :(得分:0)

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

http://pyro.sourceforge.net/

您的模拟将分布式对象提供给GUI,GUI操纵它们并读取它们的属性。

两个库都可以通过网络提供可扩展性,没有麻烦,但可以在本地运行。当您的模拟开始处理太多数字时,添加更多可提供更多分布式对象的模拟服务器。