Случайная ошибка с модулем полки (pickle.UnpicklingError: данные pickle были усечены, а EOFError: закончился ввод) - PullRequest
0 голосов
/ 03 мая 2020

Я пишу бота, который слушает потоки и уведомляет своих подписчиков о публикациях. Я работаю с модулем shelve, который дает мне то, что мне кажется случайными ошибками (обычно они не возникают, но иногда при запуске бота они появляются, и бот больше не может запускаться, пока я не уберу свой файлы базы данных). Это означает, что некоторые сообщения, которые уже были отправлены подписчикам, будут отправлены повторно из-за потери данных.

Возникают две ошибки:

EOFError: Ran out of input

и

pickle.UnpicklingError: pickle data was truncated

Мне удалось (я считаю) определить причину ошибки EOFError, которая возникает, когда бот прерывается (например, KeyboardInterrupt) во время операций ввода-вывода. Эта ошибка не так важна, так как она не будет возникать часто при использовании в реальном мире, но когда это происходит, я все равно вынужден удалить всю базу данных.

Однако ошибка «маринованные данные была усечена» остается для меня загадка, так как я не могу понять, когда это происходит или что именно идет не так. Это также случается чаще. Строка, которая вызывает ошибку: if message.id in self.db['processed_messages']:. Это первая строка, кроме конструктора, который что-то делает с базой данных.

Я надеюсь на некоторую помощь в устранении этих двух ошибок. Я включил код, который относится к ошибкам на тот случай, если кто-нибудь увидит, что может быть причиной их возникновения.

Код, относящийся к моей проблеме:

import shelve

class Bot():
    def __init__(self):
        # get data from file or create it if it does not exist
        self.db = shelve.open('database')
        # init keys if they do not exist (example: first time running the program with empty database):
        if 'processed_messages' not in self.db:
            self.db['processed_messages'] = []
        if 'processed_submissions' not in self.db:
            self.db['processed_submissions'] = []
        if 'subscribers' not in self.db:
            self.db['subscribers'] = []

    def handler(self, message):
        if message.id in self.db['processed_messages']:
            return
        self.store_data('processed_messages', message.id)

    def store_data(self, key, obj):
        """ stores data locally with shelve module """
        temp = self.db[key]
        temp.append(obj)
        self.db[key] = temp

На совершенно другом замечании: если кто-то знает лучший (более элегантный) способ работы со случаем пустой базы данных. Я также хотел бы услышать некоторый вклад, так как текущий подход в конструкторе довольно сомнительный

...