我做了这个脚本:
from gasp import *
begin_graphics()
Circle((200, 200), 60)
Line((100, 400), (580, 200))
Box((400, 350), 120, 100)
update_when('key_pressed')
end_graphics()
当我从终端启动它时,它运行良好。当我从 IDLE 运行它时,它不起作用,我没有得到任何答案(shell 提示符 (>>>) 消失但没有任何反应)。
我做了这个脚本:
from gasp import *
begin_graphics()
Circle((200, 200), 60)
Line((100, 400), (580, 200))
Box((400, 350), 120, 100)
update_when('key_pressed')
end_graphics()
当我从终端启动它时,它运行良好。当我从 IDLE 运行它时,它不起作用,我没有得到任何答案(shell 提示符 (>>>) 消失但没有任何反应)。
通常,您无法在 IDLE 中的嵌入式 Python 解释器中运行 GUI 应用程序,除非您使用的库旨在与 IDLE 集成。或者,更糟糕的是,它可能在一台机器上工作,而在另一台机器上却不行。我将在下面解释原因,但首先要相信这一点。
据我所知,gasp
的文档没有解决这个问题,但是类似的库要么警告您它们可能无法在 IDLE(easygui
、早期版本graphics
等)中工作,要么附带有关如何在 IDLE 中使用它们的特殊说明(例如,更高版本的graphics
)。
现在,也许gasp
应该设计为与 IDLE 集成,因为它是专门为新手设计的,而且其中许多新手将使用 Python 内置的 IDE。或者可能不是。但是,即使这应该是真的,那也是gasp
需要处理的事情。提交错误或功能请求,但您需要一些方法来继续工作,直到有人开始编写代码。
这里最简单的解决方案是使用不同的 IDE,它在一个完全独立的进程中运行其交互式 Python 解释器,与您自己在终端中运行它时得到的完全一样。有很多不错的选择,至少是免费的(就像啤酒一样)用于非商业用途(PyCharm、Komodo、Eclipse PyDev、带有您最喜欢的软件包集合的 emacs 等)。尽管 Stack Overflow 不是为您选择最佳的建议的好地方(如果谷歌搜索还不够,请尝试在邮件列表或论坛上询问),但几乎所有这些都可以。
另一种选择:与其使用内置于 IDE 中的解释器,不如考虑在 IDE 旁边运行增强的解释器环境(如 ipython-gtk 或带有较少软件包的 emacs)。当然,它们将不再紧密集成(“IDE”中的“I”),但根据我的经验,即使在整个团队都使用 PyCharm 或 PyDev 的环境中工作,我仍然最终会进行大部分交互式测试在 ipython 中;你可能会发现你也更喜欢那个。或者你可能不会,但试试看。
那么,为什么首先会出现问题?
首先,如果您不了解“事件循环”或“运行循环”或“主循环”是什么,请阅读为什么您的 GUI 应用程序冻结或维基百科页面或其他一些关于该想法的介绍。
通常,当您运行交互式 Python 解释器(例如,通过python
在终端中的 bash 或 C: 提示符下键入)时,它会在自己的进程中运行。因此,它可以启动一个运行循环并且永远不会返回(直到您退出),并且终端不会妨碍您。
但是当你在 IDLE 中运行交互式 Python 解释器时,它实际上与 IDLE 运行在同一个进程中,IDLE 有自己的运行循环。如果你启动了一个 runloop 并且从不返回,IDLE 的 runloop 就不会运行。这意味着它不会响应来自操作系统的事件,例如“刷新窗口”或“准备打开新窗口”,因此从用户(您)的角度来看,IDLE 和您的应用程序都只是冻结。
解决此问题的一种方法是在您的代码中为您的运行循环生成另一个线程,而不是接管主线程。(这不适用于所有 GUI 库,但它适用于某些库。这就是graphics
解决问题的方法。)另一种方法是生成一个全新的子进程来运行您的 GUI。(这适用于所有 GUI 库,但需要做更多工作——现在您必须处理进程间通信。其中一个对新手友好的matplotlib
包装器可以做到这一点。)最后,您可以通过以下方式将您的运行循环与 IDLE 的 Tkinter 运行循环集成一个驱动另一个。(并不是所有的 GUI 库都可以这样驱动,但 Tkinter 可以,并且 IDLE 可以通过猴子补丁来以这种方式工作;graphics
曾经这样做过。)但是这些都不是很简单。它们可能是gasp
本身应该做的,而不是你的代码。