为什么我在 OS X 上使用 Python/Pyglet 时会得到 NSAutoreleasePool 双重释放

Why do I get NSAutoreleasePool double release when using Python/Pyglet on OS X

我在 OS X 10.11.5 上使用 Python 3.5 和 Pyglet 1.2.4。我对这个设置很陌生。

我正在尝试查看是否可以使用事件处理来捕获击键(而不将它们回显到屏幕上)并 return 通过单独调用 [=30] 将它们一次一个地传送到主程序=] 方法。换句话说,我正在尝试使用 Piglet 事件处理,就好像它是用于此目的的可调用函数一样。

下面是我的测试程序。它设置 Pyglet 事件机制,然后调用它四次。它按预期工作,但会导致如下所示的系统消息。

import pyglet
from pyglet.window import key

event_loop = pyglet.app.EventLoop()
window = pyglet.window.Window(width=400, height=300,  caption="TestWindow")

@window.event
def on_draw():
    window.clear()

@window.event
def on_key_press(symbol, modifiers):
    global key_pressed
    if symbol == key.A:
        key_pressed = "a"
    else:
        key_pressed = 'unknown'
    pyglet.app.exit()

# Main Program
pyglet.app.run()
print(key_pressed)

pyglet.app.run()
print(key_pressed)

pyglet.app.run()
print(key_pressed)

pyglet.app.run()
print(key_pressed)

print("Quitting NOW!")

这里是为了便于阅读而插入了空行的输出。第一条消息是不同的,即使我注释掉对 piglet.app.run 的四个调用也会出现。双释放消息不会在每次调用事件处理后出现,并且不会以一致的方式出现在一个测试 运行 下一个测试中。

/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5 "/Users/home/PycharmProjects/Test Event Handling/.idea/Test Event Handling 03B.py"

2016-07-28 16:49:59.401 Python[11419:4185158]ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to /var/folders/8q/bhzsqtz900s742c17gkj_y740000gr/T/org.python.python.savedState

a

2016-07-28 16:50:02.841 Python[11419:4185158] *** -[NSAutoreleasePool drain]: This pool has already been drained, do not release it (double release).

2016-07-28 16:50:03.848 Python[11419:4185158] *** -[NSAutoreleasePool drain]: This pool has already been drained, do not release it (double release).

a

a

2016-07-28 16:50:04.632 Python[11419:4185158] *** -[NSAutoreleasePool drain]: This pool has already been drained, do not release it (double release). a Quitting NOW!

Process finished with exit code 0

基本问题:为什么会发生这种情况,我该怎么办?

备用问题:是否有更好的方法来检测和获取用户击键而不将它们回显到屏幕上。我将使用 Python 和 Pyglet 来处理图形,所以我尝试使用 Pyglet 的事件处理。

尝试玩这个简单的例子。它使用内置的 pyglet 事件处理程序将按下的键发送到一个可以处理它的函数。说明 pyglet.app 本身就是循环。您不需要创建任何其他。

#!/usr/bin/env python

import pyglet


class Win(pyglet.window.Window):
    def __init__(self):
        super(Win, self).__init__()

    def on_draw(self):
        self.clear()
        # display your output here.... 

    def on_key_press(self, symbol, modifiers):
        if symbol== pyglet.window.key.ESCAPE:
            exit(0)
        else:
            self.do_something(symbol)
        # etc....

    def do_something(symbol):
        print symbol
        # here you can test the input and then redraw

window = Win()
pyglet.app.run()