Ошибка RunTime: размер словаря изменялся во время итерации при использовании глобальных переменных - PullRequest
0 голосов
/ 17 марта 2020

На этом сайте есть несколько тем, касающихся этой же ошибки, но я не нашел ничего, что решило бы мою проблему.

Я работаю в Python 3 на клиенте чата, используя UDP en, и я «вручную» прикрепляю порядковые номера к каждому исходящему сообщению. Затем это сообщение сохраняется в глобальном словаре timed_msgs, где оно имеет следующий формат { SEQNR: [MESSAGE, TIMESTAMP] }, например, { 1: [ 'Hello', 1584443275.6280255] }. Если клиент не получает подтверждение, соответствующее порядковому номеру, в течение двух секунд, сообщение повторно отправляется и удаляется из словаря. Если подтверждение получено, он добавляется в глобальный список целых чисел rcvd_acks. В функции manage_timed_msgs код выполняется по этому списку и проверяет, есть ли какие-либо сообщения, которые соответствуют полученным подтверждениям.

Теперь этот глобальный timed_msgs можно изменить с помощью входящего подтверждения или тайм-аута. (упомянутые две секунды). Но это вызывает проблему, так как может выполнить итерацию sh, если это будет сделано, в то время как третий for-l oop проходит по ней. Код:

def manage_timed_msgs(conn: Connection):

    global timed_msgs
    global rcvd_acks

    while True:
        delete_acks = []
        for i in range(0,len(rcvd_acks)):
            try:
                del timed_msgs[rcvd_acks[i]]
                delete_acks.append(i)
            except:
                pass

        for i in range(0,len(delete_acks)):
            remove_item_number = delete_acks[-(i+1)]
            del rcvd_acks[remove_item_number]

        current_time = time.time()

        delete_keys = []
        for key in timed_msgs:
            if (current_time - timed_msgs[key][1]) > 2:
                req_send(conn, timed_msgs[key][0])
                delete_keys.append(key)

        for key in delete_keys:
            del timed_msgs[key]

Если произойдет сбой, он выдаст следующую ошибку: RuntimeError: dictionary changed size during iteration и укажет на строку for key in timed_msgs:.

Теперь я прочитал, что можно сделать копия словаря и вместо этого l oop. Мой план состоял в том, чтобы сделать это, а затем проверить в глобальном масштабе, поступили ли какие-либо новые сообщения, и объединить два (исключая те, которые были удалены в копии, поскольку они либо повторно отправляются, либо подтверждаются). Но в этом я терплю неудачу раз за разом. Любые предложения приветствуются.

...