Как передать каждое из значений списка в другую функцию?
Имеется тлеграм бот, написанный на библиотеке 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 шт):
Сейчас у вас проблема в том, что запустив задачу для первой записи, вы ждете в цикле пока она не закончится, и как только статус меняется на 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 ... или получайте поля по имени (как именно это делать, зависит от используемой БД).