CPython 2.7: Weakset data changing size during internal iteration

Terry Reedy tjreedy at udel.edu
Fri Jun 1 18:42:22 EDT 2012


On 6/1/2012 11:23 AM, Temia Eszteri wrote:
> I've got a bit of a problem - my project uses weak sets in multiple
> areas, the problem case in particular being to indicate what objects
> are using a particular texture, if any, so that its priority in OpenGL
> can be adjusted to match at the same time as it being (de)referenced
> by any explicit calls.
>> Problem is that for certain high-frequency operations, it seems
> there's too much data going in and out for it to handle - the
> following traceback is given to me (project path changed to protect
> the innocent):
>> Traceback (most recent call last):
> File "C:\foo\bar\game.py", line 279, in update
> self.player.update()
> File "C:\foo\bar\player.py", line 87, in update
> PlayerBullet((self.x + 8, self.y + 9), 0, self.parent)
> File "C:\foo\bar\player.py", line 96, in __init__
> self.sprite = video.Sprite("testbullet", 0)
> File "C:\foo\bar\video.py", line 95, in __init__
> self.opengl_id = reference_texture(self, target)
> File "C:\foo\bar\video.py", line 310, in reference_texture
> if not video_handler.textures[target].references:

I gather that the .references attribute is sometimes/always a weakset. 
To determine its boolean value, it computes its length. For regular 
sets, this is sensible as .__len__() returns a pre-computed value.
> File "C:\Python27\lib\_weakrefset.py", line 66, in __len__
> return sum(x() is not None for x in self.data)

Given that len(weakset) is defined (sensibly) as the number of currently 
active members, it must count. weakset should really have .__bool__ 
method that uses any() instead of sum(). That might reduce, but not 
necessarily eliminate your problem.
> File "C:\Python27\lib\_weakrefset.py", line 66, in<genexpr>
> return sum(x() is not None for x in self.data)
> RuntimeError: Set changed size during iteration

I can think of two reasons:
1. You are using multiple threads and another thread does something to 
change the size of the set during the iteration. Solution? put a lock 
around the if-statement so no other thread can change self.data during 
the iteration.
2. Weakset members remove themselves from the set before returning None. 
(Just a thought, in case you are not using threads).
-- 
Terry Jan Reedy


More information about the Python-list mailing list

AltStyle によって変換されたページ (->オリジナル) /