Как сделать запуск функции каждый день в 08:00?
Если добавить команду, то функция через у команду работает. Как сделать чтобы эта функция запускалась, скажем, каждый день в 08:00?
def data_r_new(message):
core.log(message.chat, message.text)
conn = sqlite3.connect(settings.DATABASE)
cursor = conn.cursor()
sql = "SELECT * FROM dovidnyk WHERE strftime('%d-%m', data_r) = strftime('%d-%m', 'now')"
cursor.execute(sql,)
result = cursor.fetchall()
for fn in result:
sql = "SELECT user_id FROM user WHERE status = True"
cursor.execute(sql,)
result = cursor.fetchall()
for i in result:
dr = datetime.strptime(fn[6], '%Y-%m-%d %H:%M:%S').strftime('%d.%m.%Y')
msg = "<i>? <u>ПІБ</u></i>: <b>{} {} {}</b>\n" \
"<i>? <u>Дата народження</u></i>: <b>{}</b>\n".format(fn[3], fn[4], fn[5], dr)
sent = bot.send_message(i[0], msg, reply_markup=keyboard, parse_mode='HTML')
Ответы (3 шт):
Вы можете запускать свои скрипты в определенное время через python-rq. Эта библиотека довольно просто подключается:
from redis import Redis
from rq import Queue
q = Queue(connection=Redis())
И планируется:
q.enqueue_at(datetime(2021, 01, 20, 8, 0), data_r_new, message)
А с помощью функции enqueue_in можно задать интервал, через который функция будет выполняться
Библиотека имеет хорошую документацию, и не требует глубокого изучения. Является в какой-то степени альтернативой для известной celery.
Запускается так же отдельным процессом (для запуска с планировщиком необходимо задать дополнительный ключ):
rq worker --with-scheduler
P.S: В качестве альтернативы так же можете посмотреть в сторону dramatiq (поддерживает приоритеты задач и их запуск через заданный промежуток времени)
.
Как возможная альтернатива.
Первое. Вероятно, надо установить специальный модуль schedule. Он не входит в перечень стандартных модулей "из коробки".
$ pip install schedule
Второе. Добавить в программу следующее:
import schedule
import time
def job():
print("I'm working...")
schedule.every().day.at("08:00").do(job)
while True:
schedule.run_pending()
time.sleep(1)
Здесь - job - это ваша функцию, которую вы хотите выполнять в 8:00.
Есть еще модуль shed из стандартной библиотеки, но там время идет в секундах от начала эпохи и придется повозиться, с тем чтобы добавлять задачу на 8:00. Однако это может оказаться полезным упражнением и ничего дополнительно не надо устанавливать...
=== Альтернатива альтернативе ===
Используем модуль строенный модуль тайм time и смекалку :-).
import time
time.localtime()
Out[42]: time.struct_time(tm_year=2021, tm_mon=1, tm_mday=18, tm_hour=13, tm_min=7, tm_sec=22, tm_wday=0, tm_yday=18, tm_isdst=0)
time.localtime().tm_hour
Out[43]: 13
Как видите, несложно узнать текущее время, используя
.tm_hour .tm_min .tm_sec
например так:
import time
...
while True:
time.sleep(1)
z = time.localtime()
if z.tm_hour == 8 and z.tm_min == 0 and tm_sec == 0:
print("Бимба")
Первый вариант: Работает нормально с polling, но с flask не работает.
from multiprocessing import *
import schedule
def start_process():
p1 = Process(target=P_schedule.start_schedule, args=()).start()
def start_schedule():
schedule.every().day.at("08:00").do(data_r_new)
while True:
schedule.run_pending()
time.sleep(1)
def data_r_new():
......
if __name__ == '__main__':
start_process()
bot.polling(none_stop=True)
Второй вариант: Работает нормально с flask.
from flask_apscheduler import APScheduler
def data_r_new():
......
scheduler = APScheduler()
if __name__ == '__main__':
if not app.debug or os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
scheduler.add_job(id ='data_r_mess_new', func = data_r_mess_new, trigger = 'cron', hour = 8, minute = 0, second = 0)
scheduler.start()
ПС. Строка if not app.debug or os.... нужна для того чтобы не приходило сообщение два раза, когда во flask включен debug=True. Если debug не включен, эту строчку можно убрать.