Python初学者图形程序出现“栈空间不足”错误
我现在正在学习Python,使用的是Zelle的入门教材。我想重现其中一个示例程序,这个程序需要一个叫graphics.py的文件。不过因为我用的是Python 3.1,而这本书是为2.x版本写的,所以我下载了一个叫GraphicsPy3.py的文件,地址是http://mcsp.wartburg.edu/zelle/python,然后把它改名为graphics.py放在我的电脑上。
名为futval_graph.py的文件内容如下:
from graphics import *
def main():
print("This program plots the growth of a 10-year investment.")
principal = eval(input("Enter the initial principal: "))
apr = eval(input("Enter the annualized interest rate: "))
win = GraphWin("Investment Grown Chart", 320, 420)
win.setBackground("white")
Text(Point(20, 230), ' 0.0K').draw(win)
Text(Point(20, 180), ' 2.5K').draw(win)
Text(Point(20, 130), ' 5.0K').draw(win)
Text(Point(20, 80), ' 7.5K').draw(win)
Text(Point(20, 30), '10.0K').draw(win)
# Rest of code is here but I've commented it out to isolate the problem.
main()
当我在一个新的IDLE会话中运行'import futval_graph'时,程序会运行,但在输入'apr'后就卡住了,没有打开新的图形窗口。当我从命令行运行这个程序时,得到的结果是:
C:\Python31>futval_graph.py
这个程序绘制了一个10年投资的增长图。
输入初始本金:后台错误处理出错:
堆栈空间不足(无限循环?)
执行时出错
"::tcl::Bgerror {堆栈空间不足(无限循环?)} {-code 1 -level 0 -errorcode NONE -errorinfo {堆栈空间不足(无限循环?)
执行时出错..."
特别让人沮丧的是,这些命令在新的IDLE会话中输入时可以正常工作。而当我在IDLE中运行'import futval_graph',在所有命令都单独运行后,futval_graph就能正常工作了。
所以我的问题是:我该如何让futval_graph.py在命令行和IDLE中都能正常运行呢?抱歉我对问题的解释有点零散。如果需要更多信息来澄清,请告诉我。
3 个回答
经过一些额外的研究,看来调用 input() 确实会影响到出现不想要的行为。
我重新写了程序,直到 input() 调用完成后才导入图形模块。在这种情况下,我没有再遇到错误,代码似乎正常运行,即使是在命令行中运行也是如此。我能够从用户那里获取参数,然后程序开始绘制图表(虽然根据示例代码,绘制的内容很少,应用程序就关闭了)。也许这个方法可以作为你问题的一个解决方案。
根本问题似乎与 tkinter 模块在一个单独线程中初始化的方式有关,以及线程之间的一些不良互动。我猜测,当从命令行运行 input() 方法时,可能会锁定某个资源,或者触发某种行为,导致 Tk 线程进入无限循环。
在网上搜索时,我发现其他用户也遇到了同样的错误,但原因各不相同。有些人在 tkinter 没有线程支持的情况下遇到这个问题,但我觉得这不适用于这里。
你的代码在使用内置的 input
函数时有问题,特别是当你传入一个非空字符串作为参数时。我猜这可能和 graphics
的线程设置有关。
如果你使用 Tkinter 的控件来读取这些输入,可能会解决你的问题。
老实说,当你下载 graphicsPy3.py
时,它上面写着:
这个图形库已经移植到 Python 3.x。仍然是实验性版本,请报告任何问题。
所以,我觉得你最好听从这个建议。
看起来Python 3版本的graphics.py有点问题。
我下载了Python 3版本,把它改名为graphics.py,然后运行了以下代码。
PS C:\Users\jaraco\Desktop> python
Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from graphics import *
>>> dir()
['BAD_OPTION', 'Circle', 'DEAD_THREAD', 'DEFAULT_CONFIG', 'Entry', 'GraphWin', 'GraphicsError', 'GraphicsObject', 'Image', 'Line', 'OBJ_ALREADY_DRAWN', 'Oval',
'Pixmap', 'Point', 'Polygon', 'Queue', 'Rectangle', 'Text', 'Transform', 'UNSUPPORTED_METHOD', '\_\_builtins\_\_', '\_\_doc\_\_', '\_\_name\_\_', '\_\_package\_\_', 'atexit', 'color_rgb', 'copy', 'os', 'sys', 'test', 'time', 'tk']
>>> error in background error handler:
out of stack space (infinite loop?)
while executing
"::tcl::Bgerror {out of stack space (infinite loop?)} {-code 1 -level 0 -errorcode NONE -errorinfo {out of stack space (infinite loop?)
while execu..."
如你所见,我遇到了同样的错误,而且我甚至还没有在这个模块里执行任何东西。问题似乎出在这个库本身,而不是你代码里的问题。
我建议你把这个问题反馈给作者,正如他所建议的那样。
我发现如果我只是简单地导入graphics模块,就不会出现这个错误。
>>> import graphics
>>> dir(graphics)
我发现如果我对你的代码做了这些修改,然后把GraphWin改成graphics.GraphWin,把Text改成graphics.Text,把Point改成graphics.Point,问题似乎就解决了,我可以从命令行运行它。
import graphics
def main():
print("This program plots the growth of a 10-year investment.")
principal = eval(input("Enter the initial principal: "))
apr = eval(input("Enter the annualized interest rate: "))
win = graphics.GraphWin("Investment Grown Chart", 320, 420)
win.setBackground("white")
graphics.Text(graphics.Point(20, 230), ' 0.0K').draw(win)
graphics.Text(graphics.Point(20, 180), ' 2.5K').draw(win)
graphics.Text(graphics.Point(20, 130), ' 5.0K').draw(win)
graphics.Text(graphics.Point(20, 80), ' 7.5K').draw(win)
graphics.Text(graphics.Point(20, 30), '10.0K').draw(win)
# Rest of code is here but I've commented it out to isolate the problem.
main()
为什么会这样呢?其实不应该这样。看起来graphics.py模块有一些副作用,导致它的表现不正常。
我怀疑在Python 2.x版本下,你不会遇到这些错误。