python memory leak
Question: I have an array of 'cell' objects created like so:

    
    
    class Cell:
      def __init__(self, index, type, color):
        self.index = index
        self.type = type
        self.score = 0
        self.x = index%grid_size
        self.y = int(index/grid_size)
        self.color = colour
    
    
    alpha = 0.8
    b = 2.0
    grid_size = 100
    scale = 5
    
    number_cells = grid_size*grid_size
    num_cooperators = int(number_cells*alpha)       
    cells = range(number_cells)
    random.shuffle(cells)
    cooperators = cells[0:num_cooperators]
    defectors = cells[num_cooperators:number_cells]
    cells = [Cell(i, 'C', blue) for i in cooperators]
    cells += [Cell(i, 'D', red) for i in defectors]
    cells.sort(compare)
    

I am grabbing attributes from them in a loop like so:

    
    
    while 1:
        pixArr = pygame.PixelArray(windowSurfaceObj)
        for cell in cells:
            x = cell.x
            y = cell.y
            color = cell.color
            for y_offset in range(0,scale):
                for x_offset in range(0,scale):
                    pixArr[x*scale + x_offset][y*scale + y_offset] = color
        del pixArr
        pygame.display.update()
    

I am leaking memory like crazy... what's going on?


Answer: There appears to be a bug in PixelArray.

The following code replicates the memory leak by setting a single pixel each
loop, and you don't even have to update the display to cause the problem:

    
    
    import pygame, sys
    from pygame.locals import *
    ScreenWidth, ScreenHeight = 640, 480
    pygame.init()
    Display = pygame.display.set_mode((ScreenWidth,ScreenHeight), 0, 32)
    pygame.display.set_caption('Memory Leak Test')
    while True:
        PixelArray = pygame.PixelArray(Display)
        PixelArray[ScreenWidth-1][ScreenHeight-1] = (255,255,255)
        del PixelArray
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
    #pygame.display.update()
    

If you can handle the performance hit, replacing direct pixel setting with
(very short) lines avoids the memory leak, ie: pygame.draw.line(Display,
Colour, (X,Y), (X,Y), 1)

