Не работает метод cursor.execute в библиотеке sqlite3 на Python

Сегодня пытался подключить к своему телеграм боту на питоне датабазу sqlite3 - сначала всё шло как по маслу, но в один момент просто перестала работать часть кода, абсолютно без причины. Пытался пофиксить путём перезагрузки ПК, создания нового проекта, но всё зря. Облегчил код, полный дать не могу, в общем сейчас выводится только, скажем так, "Сообщение до", но также должно и "Сообщение после", но оно решает не выводиться из-за нерабочего cursor.execute, нужно сделать так, чтобы выводились оба сообщения не выводится "Сообщение после"

import sqlite3
import telebot
import time

bot = telebot.TeleBot(token="токен")

database = sqlite3.connect("database.db")
cursor = database.cursor()

@bot.message_handler(commands=["start"])
def start_message(message):
    bot.send_message(chat_id=message.chat.id, text="Сообщение до")
    cursor.execute("SELECT * FROM database")
    bot.send_message(chat_id=message.chat.id, text="Сообщение после")

while True:
    try:
        bot.polling(none_stop=True, timeout=360)
    except Exception:
        time.sleep(5)

Ответы (2 шт):

Автор решения: DNS2000

в общем в комментах мне написали про бездумное использование except Exception (хоть я и не прикладывал полный код и вырезал нормальный обработчик), но после того как я оставил только bot.polling, то ничего не поменялось! В общем фастом накатил десятку на запасной ссд, и протестировав там АБСОЛЮТНО ТАКОЙ ЖЕ код с except Exception - он заработал, я не знаю что делать дальше, но вопрос закрыт)

UPD: ответом на вопрос всё-таки оказалось добавление параметра check_same_thread=False в коннект датабазы, хотя я делал это до этого, но ничего не выходило, но сейчас пробежался по всем моим действиям, которые я делал вчера, и это вдруг заработало, я не знаю почему у меня всё работает через раз))

→ Ссылка
Автор решения: artur1214

Я бы на вашем месте добавил в except блоке вывод ошибки, чтобы разобраться что не так:

while True:
    try:
        bot.polling(none_stop=True, timeout=360)
    except Exception as exc: # сохранение ошибки в переменную
        print(exc)  # Вывод ошибки
        time.sleep(5)

А еще перенес бы try/catch, если он необходим, в конкретную функцию обработчик, чтобы видеть ошибку конкретной функции, и не разбраться с тем, как работает polling (Возможно при передаче в except блок, бот перестает вообще перестает слушать сеть)

Вообще, основываясь на том, как вы описали проблему, могу предположить несколько вариантов:

1) Возможно ваша сборка python имеет проблемы с sqlite3.

По сути, поддержка sqlite3, это отдельный модуль python, если вы собирали python из исходников (часто делают на linux) то при компиляции ваш python просто собрался без нормальной поддержки sqlite. Но если вы просто скачали готовый python под windows, это очень мало вероятно

2) У вас проблемы с многопоточностью:

Исходный код библиотеки telebot описывает вот такой конструктор для класса telebot.TeleBot:

def __init__(
            self, token: str, parse_mode: Optional[str]=None, threaded: Optional[bool]=True,
            skip_pending: Optional[bool]=False, num_threads: Optional[int]=2,
            next_step_backend: Optional[HandlerBackend]=None, reply_backend: Optional[HandlerBackend]=None,
            exception_handler: Optional[ExceptionHandler]=None, last_update_id: Optional[int]=0,
            suppress_middleware_excepions: Optional[bool]=False, state_storage: Optional[StateStorageBase]=StateMemoryStorage(),
            use_class_middlewares: Optional[bool]=False, 
            disable_web_page_preview: Optional[bool]=None,
            disable_notification: Optional[bool]=None,
            protect_content: Optional[bool]=None,
            allow_sending_without_reply: Optional[bool]=None,
            colorful_logs: Optional[bool]=False
    ):
    ...

Обратите внимание на параметр threaded, который по умолчанию равен True.

Если данный параметр не передать явно как False, то Telebot будет запускать обработчики в новых потоках.

См. 282 строку

[См. 55 строку

При этом документация python sqlite3 описывает параметр check_same_thread для sqlite3.connect

check_same_thread (bool) – If True (default), ProgrammingError will be raised if the database connection is used by a thread other than the one that created it. If False, the connection may be accessed in multiple threads; write operations may need to be serialized by the user to avoid data corruption. See threadsafety for more information.

Идея такая: база данных sqlite3 это просто файл на диске, и не расчитана на многопоточную запись. Если несколько потоков будут использовать одно подключение, то есть шанс того, что данные будут в итоге повреждены и в бае будет не то, что вы ожидаете.

См. документацию для подробностей

Итог:

  1. Вы можете использовать параметр check_same_thread, чтобы sqlite не проверял какой поток использует соединение, и не вызывал ошибку. Но это может привести к ошибкам при записи.

  2. Вы можете отключить многопоточность:

bot = telebot.TeleBot(token="токен", threaded=False)

Чтобы telebot не использовал многопоточность. Но (не проводил тесты, однако) подозреваю, что это может привести к замедлению работы бота, при большом количестве пользователей.

  1. Вы можете использовать более высокоуровневые библиотеки/ORM для связи с базой данных, например ORM SQLAlchemy

  2. Я вы можете использовать асинхронные бибилотеки, такие как aiogram и aiosqlite, позволяющие избежать задержек связанных с операциями ввода/вывода (запись в базу, отправка ответа пользователю)

Причем, асинхронность в python по умолчанию работает в одном потоке, так что и проблем с многопоточностью у вас быть не должно.

→ Ссылка