Как передать каждое из значений списка в другую функцию?

Имеется тлеграм бот, написанный на библиотеке aiogram. Пытаюсь реализовать такой функционал: по команде берутся значения из БД и инициируется таск на выполнение функции с определенным интервалом (с помощью библиотеки aioschedule). Код на данный момент выглядит так:

@dp.message_handler(commands=['check'])
async def cycle_restart(msg: types.Message):
    cursor.execute('SELECT * FROM table WHERE status = ?', ('correct',))
    rec = cursor.fetchall()
    for row in rec:
        code = row[3] #уникальный идентификатор
        uid = row[1] #ID пользователя
        job = aioschedule.every(5).seconds.do(count, c_id=code, u_id=uid)
        while True:
            await aioschedule.run_pending()
            cursor.execute('SELECT status FROM table WHERE id = ?', (code,))
            rec = cursor.fetchall()
            for row in rec:
                if row[0] == 'stop':
                    aioschedule.cancel_job(job)
                    return
            await asyncio.sleep(1)

В итоге, даже если в БД присутствует 1+ подходящих строк, то берется только первая и запускается 1 таск. Никак не могу сообразить, как поправить цикл, чтобы задание назначалось с каждой из переменных, полученных из БД.


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

Автор решения: Roman-Stop RU aggression in UA

Сейчас у вас проблема в том, что запустив задачу для первой записи, вы ждете в цикле пока она не закончится, и как только статус меняется на stop, вы делаете выход из функции:

   if row[0] == 'stop':
       aioschedule.cancel_job(job)
       return

и все остальные записи выбранные первым запросом пропускаются.

Похоже, что вы хотите запустить задачи для всех записей и ждать, когда они все закончатся. Если не изменять сильно структуру кода, то вам нужно делать как-то так:

@dp.message_handler(commands=['check'])
async def cycle_restart(msg: types.Message):
    cursor.execute('SELECT * FROM table WHERE status = ?', ('correct',))
    rec = cursor.fetchall()
    jobs = {}
    for row in rec:
        code = row[3] #уникальный идентификатор
        uid = row[1] #ID пользователя
        job = aioschedule.every(5).seconds.do(count, c_id=code, u_id=uid)
        jobs[code] = job

    for code, job in jobs.items(): # повторяем для каждой запущенной задачи
        while True:     # этот цикл ждет когда завершится задача с кодом code
            await aioschedule.run_pending()
            cursor.execute('SELECT status FROM table WHERE id = ?', (code,))
            # т.к. code уникальный - запись всегда одна, можно делать fetchone
            status_row = cursor.fetchone()
            if status_row[0] == 'stop':
                aioschedule.cancel_job(job)
                continue  # выходим из цикла для текущей задачи
            await asyncio.sleep(1)

Еще одно замечание. Делать запрос SELECT * FROM table WHERE status = ?, а потом читать колонки по индексу - ненадежно, так как порядок полей, которые БД возвращает при использовании *, может измениться. Или явно указывайте имена полей SELECT uid, code, и т.д FROM ... или получайте поля по имени (как именно это делать, зависит от используемой БД).

→ Ссылка