Задать вопрос
Nynchezyabka
@Nynchezyabka

Asyncio + PySide6 + Telethon: список чатов и треды грузятся 30 минут — где искать причину?

Делаю десктопное приложение на Python (PySide6 + Telethon + SQLite) для парсинга Telegram-чатов. Проект в открытом доступе:
github.com/Nynchezyabka/RozittaParser

Сразу честно: я не программист, проект создан в формате вайбкодинга потому что сначала была одна задача на консольный скрипт, а потом я просто не смогла остановиться. Поэтому буду очень благодарна за объяснения простым языком — я понимаю что происходит в программе, но не всегда понимаю почему и как это починить. А сейчас прямо очень нужно это всё в связи с текущим положением дел.

Столкнулась с двумя проблемами и не могу понять — это мой баг или внешние ограничения Telegram API.

**Проблема 1: список чатов загружается ~30 минут**
Используется GetDialogs через Telethon. При этом отдельный консольный скрипт с той же логикой работает значительно быстрее.
Подозреваю что проблема в том как asyncio event loop взаимодействует с потоком PySide6 — но не уверена.

Вот реальный пример из логов — скачивание обычной группы без медиафайлов, только текст:

16:23:38 — начало (total_est=47998 сообщений)
16:24:28 — 100 сообщений
16:27:39 — 200 сообщений
...
20:07:53 — 12400 сообщений (всё ещё идёт)

То есть ~100 сообщений в среднем за 2-5 минут.
Без единого медиафайла, только текст.
Это нормальная скорость для Telethon или что-то явно не так?

**Проблема 2: database is locked**
SQLite, WAL-режим включён, thread-local соединения реализованы,batch insert настроен (по идее). Ошибка всё равно периодически появляется при одновременной работе нескольких воркеров (Parse → STT → Export).

**Архитектура:**
- asyncio event loop живёт в отдельном потоке
- GUI в основном потоке Qt
- общение через Qt-сигналы
- каждый воркер создаёт собственный TelegramClient
  • Вопрос задан
  • 455 просмотров
Подписаться 2 Средний 2 комментария
Помогут разобраться в теме Все курсы
  • Нетология
    Python-разработчик: расширенный курс + нейросети
    12 месяцев
    Далее
  • Яндекс Практикум
    Python-разработчик
    10 месяцев
    Далее
  • Skillbox
    Профессия Python-разработчик + ИИ
    10 месяцев
    Далее
Решения вопроса 1
Nynchezyabka
@Nynchezyabka Автор вопроса
Вопрос решен с помощью прокси и кэша)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@eminsk
developer python, javascripts
https://github.com/eminsk/RozittaParser
все правки то что считал сделал там если какие вопросы пиши уже в моем репозитарии уже
если какие будут вопросы.

Резузультаты теста
uv run pytest
============================= test session starts =============================
platform win32 -- Python 3.14.3, pytest-9.0.2, pluggy-1.6.0
rootdir: C:\proekts\RozittaParser
configfile: pyproject.toml
collected 86 items
tests\test_core\test_database.py .................. [ 20%]
tests\test_core\test_merger.py ............ [ 34%]
tests\test_core\test_utils.py .............................. [ 69%]
tests\test_features\test_export.py ........... [ 82%]

Я разобрал код, и у тебя тут не одна причина, а несколько конкретных узких мест.
Главное: это не “просто Telethon медленный”. В проекте есть реальные места, которые сами создают тормоза и database is locked.
Что у тебя тормозит на самом деле
- Список чатов тормозит не столько из-за get_dialogs(), сколько из-за доп. запросов после него: в features/chats/chats_api.py:183 список диалогов грузится один раз, но потом в features/chats/chats_api.py:229 для каждого канала идет GetFullChannelRequest, чтобы проверить linked group. Если каналов много, это уже пачка сетевых запросов.
- Топики форума могут резко тормозить, если прямой API не срабатывает и код уходит в fallback-скан сообщений: features/chats/chats_api.py:381. Это уже не “получить список веток”, а “пройтись по сообщениям и угадать ветки”.
- Текстовый парсинг у тебя явно ненормально медленный. Самая сильная причина, которую я вижу: очень агрессивное логирование. В features/parser/api.py:826 есть debug-лог практически на каждое сообщение, а в core/logger.py:124 и core/logger.py:197 файл-лог включен на DEBUG вообще для всего приложения. На больших чатах это легко убивает скорость.
- В features/parser/api.py:530 ты вызываешь iter_messages(...) без wait_time. У Telethon на больших историях это часто добавляет внутренние паузы между запросами. Это не объясняет 4 часа целиком, но добавляет тормоз.
- Еще один баг: по документации ты рассчитываешь на batch insert, но фактически во время основного прохода строки копятся в памяти и пишутся в БД только в самом конце: features/parser/api.py:387, features/parser/api.py:416. То есть во время “долгого парсинга текста” тормозит не SQLite, а сеть/логирование/итерация.
Откуда берется database is locked
Тут у тебя, похоже, смешиваются две разные блокировки.
- Telethon session — это тоже SQLite. Если одновременно живы два TelegramClient на одном .session, получаешь тот же database is locked.
- Архивная БД сообщений — отдельная SQLite, и она тоже может ловить lock.
Самый опасный кусок у тебя тут: ui/main_window.py:1590.
- Перед стартом ParseWorker окно ждет ChatsWorker и TopicsWorker только 30_000 мс.
- Если загрузка чатов реально висит дольше, ты все равно потом стартуешь парсер: ui/main_window.py:1606.
- Это значит, что ChatsWorker еще может держать Telethon session, а ParseWorker уже открывает новый TelegramClient.
Это очень похоже на главный источник твоего периодического database is locked.
То есть проблема не “SQLite плохой”, а “два клиента пересеклись по времени на одном session-файле”.
Что я считаю корнем проблемы по приоритету
1. Слишком подробный DEBUG-лог в файл на больших объемах — core/logger.py:124, core/logger.py:197, features/parser/api.py:826.
2. Старт ParseWorker, пока ChatsWorker/TopicsWorker еще не закончили — ui/main_window.py:1590.
3. Дорогие дополнительные запросы для linked group после get_dialogs() — features/chats/chats_api.py:229.
4. Возможный fallback-скан топиков вместо прямого API — features/chats/chats_api.py:381.
5. Batch insert реализован не так, как ожидается: запись откладывается до конца — features/parser/api.py:416.
Почему твои цифры выглядят подозрительно
- 48k текстовых сообщений за почти 4 часа — это слишком медленно.
- Даже если Telegram иногда душит историю, это не должно быть настолько плохо на чистом тексте.
- Значит, почти наверняка тормозит не только Telegram API, а еще и твоя обвязка вокруг него.
Что я бы исправлял первым делом
- Временно понизить файловый лог с DEBUG до INFO и убрать per-message debug-лог.
- Не запускать ParseWorker, если ChatsWorker или TopicsWorker еще живы. Не “подождать 30 секунд”, а именно не запускать вообще до полного завершения.
- В iter_messages(...) явно задать wait_time=0 или маленькое значение и заново замерить.
- Кэшировать linked-group данные, чтобы не делать GetFullChannelRequest для каждого канала каждый раз.
- Писать batch в БД периодически по ходу парсинга, а не только в конце.
- Добавить retry на lock в insert_messages_batch() и upsert_messages_batch() в core/database.py:351 и core/database.py:402.
Ответ написан
Ваш ответ на вопрос

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

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