Eu tenho uma hospedagem na web Flask sem acesso a cron
comando.
Como posso executar alguma função Python a cada hora?
Você pode usar BackgroundScheduler()
a partir APScheduler pacote (v3.5.3):
import time
import atexit
from apscheduler.schedulers.background import BackgroundScheduler
def print_date_time():
print(time.strftime("%A, %d. %B %Y %I:%M:%S %p"))
scheduler = BackgroundScheduler()
scheduler.add_job(func=print_date_time, trigger="interval", seconds=3)
scheduler.start()
# Shut down the scheduler when exiting the app
atexit.register(lambda: scheduler.shutdown())
Observe que dois desses agendadores serão iniciados quando o Flask estiver no modo de depuração. Para mais informações, verifique esta questão.
flask
tivesse umApp.runonce
ouApp.runForNseconds
você poderia alternar entreschedule
e o corredor do frasco, mas esse não é o caso, então a única maneira por enquanto é usando issoVocê poderia fazer uso de
APScheduler
em seu aplicativo Flask e executar seus trabalhos por meio de sua interface:fonte
lambda
dentroatexit.register
?atexit.register
precisa de uma função para chamar. Se apenascron.shutdown(wait=False)
passarmos, estaremos passando o resultado da chamadacron.shutdown
(que provavelmente éNone
). Então, em vez disso, passamos uma função de argumento zero, e em vez de dar a ela um nome e usar uma instruçãodef shutdown(): cron.shutdown(wait=False)
eatexit.register(shutdown)
, em vez disso, registramos inline comlambda:
(que é uma expressão de função de argumento zero .)Eu sou um pouco novo com o conceito de agendadores de aplicativos, mas o que encontrei aqui para APScheduler v3.3.1 , é algo um pouco diferente. Acredito que para as versões mais recentes, a estrutura do pacote, os nomes das classes, etc., mudaram, então estou colocando aqui uma solução nova que fiz recentemente, integrada com um aplicativo Flask básico:
Eu também estou deixando este Gist aqui , se alguém tiver interesse em atualizações para este exemplo.
Aqui estão algumas referências, para leituras futuras:
fonte
apscheduler.schedulers.background
, pois pode ser possível que você encontre outros cenários úteis para sua aplicação. Saudações.Você pode tentar usar o BackgroundScheduler do APScheduler para integrar o trabalho de intervalo em seu aplicativo Flask. Abaixo está o exemplo que usa blueprint e app factory ( init .py):
Espero que ajude :)
Ref:
fonte
Para uma solução simples, você pode adicionar uma rota, como
Em seguida, adicione um cron job do Unix que efetua POST neste terminal periodicamente. Por exemplo, para executá-lo uma vez por minuto, no tipo de terminal
crontab -e
e adicionar esta linha:(Observe que o caminho para curl deve ser concluído, pois quando o trabalho for executado, ele não terá seu PATH. Você pode descobrir o caminho completo para curl em seu sistema
which curl
)Eu gosto disso porque é fácil testar o trabalho manualmente, não tem dependências extras e como não há nada de especial acontecendo, é fácil de entender.
Segurança
Se quiser proteger seu cron job com senha, você pode
pip install Flask-BasicAuth
e, em seguida, adicione as credenciais à configuração do aplicativo:Para proteger com senha o endpoint do trabalho:
Então, para chamá-lo de seu cron job:
fonte
Outra alternativa pode ser usar Flask-APScheduler, que funciona bem com o Flask, por exemplo:
Mais informações aqui:
https://pypi.python.org/pypi/Flask-APScheduler
fonte
Um exemplo completo usando agendamento e multiprocessamento, com controle ligado e desligado e parâmetro para run_job (), os códigos de retorno são simplificados e o intervalo é definido para 10seg, mude para
every(2).hour.do()
para 2 horas. O cronograma é bastante impressionante, ele não oscila e eu nunca vi isso com mais de 100ms de atraso ao programar. Usando multiprocessamento em vez de threading porque tem um método de terminação.Você testa isso apenas emitindo:
A cada 10 segundos, o cronômetro está ativado, ele emitirá uma mensagem de cronômetro para o console:
fonte
Você pode querer usar algum mecanismo de fila com agendador como o agendador RQ ou algo mais pesado como Celery (provavelmente um exagero).
fonte