pythondiscordmembers

Discord.py Runtime error with dictionaries


So, I've been trying to make a bot which loops through all the members in my server. I'm using the get_all_members() generator to do so.

for member in client.get_all_members():
      userName = str(member.name)
      userGame = str(member.game)
      userID = str(member.id)
      print(userName, userGame, userID)
      await client.send_message(message.channel, "User " + userName + " 
      (<@" + userID + ">) is playing " + userGame)

I got this error randomly during runtime:

File "C:\Program Files\Python36\lib\site-packages\discord\client.py", line 307, in _run_event 
    yield from getattr(self, event)(*args, **kwargs) 
File "C:\Users\Stefan\Source\Repos\AABot3\AABot3\AABot3.py", line 41, in on_message 
    for member in client.get_all_members(): 
File "C:\Program Files\Python36\lib\site-packages\discord\client.py", line 595, in get_all_members 
    for member in server.members: 
RuntimeError: dictionary changed size during iteration – 

How can I avoid this error?


Solution

  • Try making a list out of get_all_members before looping over it.

    for member in list(client.get_all_members()):
        ...
    

    What's happening is that Server objects store their Members in a dictionary. When you await a coroutine, you allow other coroutines to run while you wait, one of which keeps Server objects up to date. Whenever the membership of a Server changes, the dictionary is changed as well. Because you should never iterate over something as it changes, Python detects this and terminates the program.

    By reading the values into a list first, we won't notice when the dictionary changes.

    The latest version has changed this behavior, which is discussed here