@haroldlor

Стираются данные при записи в коде телеграм бота, как исправить?

в общем, как я не менял формат файла куда производиться импорт данных, они удаляются после где-то 600-ой 700-ой строчки, до 400-ой (речь про suggested_photos.csv)

помогите, а то я с этой шнягой мучаюсь уже полгода

import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton, ChatPermissions
import time
import csv
from datetime import datetime
import os
import math
from collections import defaultdict

bot_token = ''
editors_chat_id = ''
channel_username = ''

bot = telebot.TeleBot(bot_token)

def load_allowed_users():
    try:
        with open('allowed_users.csv', 'r') as file:
            reader = csv.reader(file)
            return [int(row[0]) for row in reader]
    except FileNotFoundError:
        return []

def save_allowed_users():
    with open('allowed_users.csv', 'w', newline='') as file:
        writer = csv.writer(file)
        for user_id in allowed_users:
            writer.writerow([user_id])

allowed_users = load_allowed_users()

def save_data():
    with open('suggested_photos.csv', 'a', newline='') as file:
        fieldnames = ['file_id', 'photo_id', 'username', 'user_id', 'editor_id', 'message_id', 'status', 'timestamp']
        writer = csv.DictWriter(file, fieldnames=fieldnames)
        writer.writeheader()

        for file_id, media_data in suggested_photos.items():
            writer.writerow({
                'file_id': file_id,
                'photo_id': media_data.get('photo_id', ''),
                'username': media_data.get('username', ''),
                'user_id': media_data.get('user_id', ''),
                'editor_id': media_data.get('editor_id', ''), 
                'message_id': media_data.get('message_id', ''),
                'status': media_data.get('status', ''),
                'timestamp': media_data.get('timestamp', ''),
            })

def load_data():
    try:
        with open('suggested_photos.csv', 'r') as file:
            reader = csv.DictReader(file)
            return {row['file_id']: {k: v if v != '' else None for k, v in row.items()} for row in reader}
    except FileNotFoundError:
        return {}

suggested_photos = load_data()


логи с сервера

/root/.pm2/logs/main-error.log last 15 lines:
2|main | File "/usr/local/lib/python3.8/dist-packages/telebot/__init__.py", line 1118, in __threaded_polling
2|main | raise e
2|main | File "/usr/local/lib/python3.8/dist-packages/telebot/__init__.py", line 1074, in __threaded_polling
2|main | self.worker_pool.raise_exceptions()
2|main | File "/usr/local/lib/python3.8/dist-packages/telebot/util.py", line 147, in raise_exceptions
2|main | raise self.exception_info
2|main | File "/usr/local/lib/python3.8/dist-packages/telebot/util.py", line 90, in run
2|main | task(*args, **kwargs)
2|main | File "/usr/local/lib/python3.8/dist-packages/telebot/__init__.py", line 6801, in _run_middlewares_and_handler
2|main | result = handler['function'](message)
2|main | File "/root/rtd/main.py", line 484, in process_photo
2|main | save_data()
2|main | File "/root/rtd/main.py", line 38, in save_data
2|main | for file_id, media_data in suggested_photos.items():
2|main | RuntimeError: dictionary changed size during iteration
  • Вопрос задан
  • 81 просмотр
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Читаем доки.
Синхронный телебот по умолчанию выполняет обработчики в пуле потоков, чтобы один медленный обработчик не ставил колом всего бота. Как следствие, ты ловишь т.н. состояние гонки, когда несколько обработчиков (или несколько копий одного обработчика), работающих в разных потоках, одновременно обращаются к одному ресурсу - например, к твоему словарю suggested_photos, или к файлу, или ещё к чему. Косяки при этом могут возникать самые весёлые - и, что самое неприятное, они будут то появляться, то исчезать в зависимости от порядка исполнения потоков.

Так что либо пробуй отключать многопоточность параметром конструктора Telebot (ссылку на доки я дал), либо разбирайся, как писать многопоточные приложения - например, защищая глобальные ресурсы бота мьютексом.

Также можешь попробовать перейти на асинхронный вариант телебота, но там нужно понимать как вообще устроены асинхронные приложения.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы