Как остановить выполнение задания, работая с библиотекой schedule в Python?

Для добавления определенного функционала телеграм боту, пытаюсь написать скрипт, который будет по команде от пользователя вносить изменения в БД sqlite до достижения определенных условий или до новой команды от пользователя. Для этого пытаюсь использовать библиотеку schedule (или асинхронную aioschedule), но никак не могу прервать цикл выполнения запущенного задания.

import schedule
import time
import sqlite3

conn = sqlite3.connect('db/gecko.db', check_same_thread=False)
cursor = conn.cursor()

def some_task():
    cursor.execute('UPDATE table SET column = column + 1 WHERE id = ?', ('123',))
    conn.commit()

def start():
    job = schedule.every(2).seconds.do(some_task)
    while True:
        schedule.run_pending()
        cursor.execute('SELECT column FROM table WHERE id = ?', ('123',))
        recs = cursor.fetchall()
        print(schedule.get_jobs())
        for row in recs:
            if row[0] == 70:
                schedule.cancel_job(job)
                break
        time.sleep(1)

if input('Start?') == 'y':
    start()

В итоге обновление данных прекращается, но цикл не прерывается, судя по тому, что в консоль продолжается вывод строки print(schedule.get_jobs())

И стоит ли вообще управлять изменением в БД из основного кода, учитывая, что пользователей, в теории, может быть 100+, и у для каждого будет запускаться свой цикл? Или лучше написать внешний скрипт, который будет парсить данные с БД и начинать цикл при считывании определенного триггера в БД?


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

Автор решения: CrazyElf
def start():
    ...
    while True: # <-- 1-й цикл
        ...
        for row in recs: # <-- 2-й цикл
            if row[0] == 70:
                schedule.cancel_job(job)
                break # <-- прерываем внутренний цикл

break прерывает только один, самый внутренний цикл, а у вас два вложенных цикла, внешний цикл продолжает работать. Чтобы выйти из обоих циклов сразу вам тут можно использовать return:

            if row[0] == 70:
                schedule.cancel_job(job)
                return # <-- прерываем работу всей функции

Если бы циклы не были внутри функции, пришлось бы делать более сложно, например, заводить переменную, которую потом сбрасывать:

    do_job = True
    while do_job: # <-- 1-й цикл
        ...
        for row in recs: # <-- 2-й цикл
            if row[0] == 70:
                schedule.cancel_job(job)
                do_job = False # <-- чтобы прервать внешний цикл
                break # <-- прерываем внутренний цикл
→ Ссылка