我使用列表错了吗?这个简单的python / pyglet代码中的内存泄漏

时间:2013-06-14 08:00:35

标签: python list memory-leaks pyglet

我在pyglet中写了一个简单的'避免堕落的敌人'类型的游戏。对象在屏幕上方生成,向下移动,并在通过可见屏幕下方时被破坏。但是,我正在做一些非常错误的事情,程序运行的时间越长,对象的数量就越多。 (它正在放慢速度,我发现了objgraph的问题。)当我删除这个类时,问题就消失了。

坠落的敌人类:

class Enemy(pyglet.sprite.Sprite):
    def __init__(self, **kwargs):
        super(Enemy, self).__init__(img=images.enemy_anim["front"], **kwargs)
        self.out_of_bounds = False

    def update(self, dt):
        self._move(dt)
        self._check_boundaries(dt)
        self._check_kill_condition()

    def _move(self, dt):
        self.y -= ENEMY_SPEED * dt

    def _check_boundaries(self, dt):
        if self.y + self.height < 0:
            self.out_of_bounds = True

    def _check_kill_condition(self):
        if self.out_of_bounds:
            enemy_list.remove(self)
            self.delete

主要方法代码:

enemy_list = []

def add_enemy(*args, **kwargs):
    randx = random.randint(0,
               WINDOW_WIDTH - images.enemy_anim["front"].get_max_width())
    randy = WINDOW_HEIGHT + images.enemy_anim["front"].get_max_height()
    enemy_list.append(Enemy(x=randx, y=randy, batch=update_batch))

def update(dt):
    for sprite in enemy_list:
        sprite.update(dt)

#send the above functions to the pyglet scheduler
pyglet.clock.schedule_interval(update, 1/TICKS_PER_SECOND)
pyglet.clock.schedule_interval(add_enemy, 1/ENEMY_ADD_RATE)

我的敌人动画存储在字典中的单独模块(图像)中(images.enemy_anim)。

我在列表中创建了一个带有引用的敌人。

当敌人死亡时,我告诉它将自己从列表中删除。我在运行时检查了列表的长度,它始终是合适的长度。所以这份名单并没有失控。从列表中删除后,对象应该没有引用,对吗?

我做错了什么?

编辑:

问题是我有self.delete而不是self.delete()。愚蠢的错误......

2 个答案:

答案 0 :(得分:5)

我没有删除自己方法中的对象,而是采用不同的方法并在附加的schedule_interval中删除精灵,如下所示:

def delete_enemy(*args, **kwargs):
    items_to_delete = []
    for enemy in enemy_list:
        if enemy.out_of_bounds:
            items_to_delete.append(enemy)
    for item in items_to_delete:
        enemy_list.remove(item)

pyglet.clock.schedule_interval(delete_enemy)

当然,请移除self._check_kill_condition()中的行Enemy.update

编辑:我不知道pyglet,但是如果这种方法也不起作用,那么pyglet中的某些东西会保留对你的精灵的引用。精灵可以在画布或类似对象中引用。在pyglet中应该有一个API调用来完全删除一个Sprite(即从画布中删除)。然后应在enemy_list.remove(item)电话后立即使用此通话。

答案 1 :(得分:0)

正如Bakuriu在上面的评论中指出的那样,问题是我只是忘记了pyglet精灵delete方法中的一对括号。一个简单而明显的错误导致了一个巨大的问题...