Python 3.9 - 调度具有不同参数的异步函数的定期调用

Yur*_*iev 6 python scheduled-tasks python-3.x python-asyncio

如何在python 3.9中实现按计划周期调用具有不同参数的异步函数的功能?该功能应该适用于任何操作系统(Linux、Windows、Mac)

我有一个函数 fetchOHLCV 从交易所下载市场数据。该函数有两个输入参数 - 对、时间范围。根据货币对和时间范围值,该函数从交易所下载数据并将其存储在数据库中。

目标 - 使用不同的参数在不同的时期调用此函数。

1) fetchOHLCV(pair ='EUR/USD', timeframe="1m") - each minute
2) fetchOHLCV(pair ='EUR/USD', timeframe="1h") - each new hour.
3) fetchOHLCV(pair ='EUR/USD', timeframe="1d") - each new day 
4) fetchOHLCV(pair ='EUR/USD', timeframe="1w") - each new week
Run Code Online (Sandbox Code Playgroud)

目前,我没有在 python 中进行调度的经验,并且我不知道哪些库最适合我的任务,并且我对实现类似任务的最佳实践感兴趣。

thi*_*ths 5

在这里,您使用apschedulers AsyncIOScheduler,它可以自然地与异步函数配合使用

scheduler = AsyncIOScheduler()
scheduler.add_job(fetchOHLCV, trigger=tr)
scheduler.start()
Run Code Online (Sandbox Code Playgroud)

tr 是触发对象。您可以使用IntervalTrigger或 aCronTrigger来安排它。建议shutdown()在程序结束后对调度程序对象进行操作

或者

您可以使用run_coroutine_threadsafe将协程调度到事件循环

asyncio.run_coroutine_threadsafe(async_function(), bot.loop)
Run Code Online (Sandbox Code Playgroud)

asyncio的工作示例Python3.9

import asyncio

async def periodic():
    while True:
        print('periodic')
        await asyncio.sleep(1) #you can put 900 seconds = 15mins

def stop():
    task.cancel()

loop = asyncio.get_event_loop()
loop.call_later(5, stop) #increase end time as per your requirement
task = loop.create_task(periodic())

try:
    loop.run_until_complete(task)
except asyncio.CancelledError:
    pass
Run Code Online (Sandbox Code Playgroud)

执行

正如您所看到的,异步函数是按照 的调度调用的1second,并且stop函数是在 处调用的5th second。尝试实施这个,可能会解决你的问题


ale*_*ame 4

作为一个随时可用的解决方案,您可以使用aiocron库。如果你不熟悉cron表达式语法,可以使用这个在线编辑器来检查。

示例(这适用于任何操作系统):

import asyncio
from datetime import datetime
import aiocron


async def foo(param):
    print(datetime.now().time(), param)


async def main():
    cron_min = aiocron.crontab('*/1 * * * *', func=foo, args=("At every minute",), start=True)
    cron_hour = aiocron.crontab('0 */1 * * *', func=foo, args=("At minute 0 past every hour.",), start=True)
    cron_day = aiocron.crontab('0 9 */1 * *', func=foo, args=("At 09:00 on every day-of-month",), start=True)
    cron_week = aiocron.crontab('0 9 * * Mon', func=foo, args=("At 09:00 on every Monday",), start=True)

    while True:
        await asyncio.sleep(1)

asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)

输出:

15:26:00.003226 At every minute
15:27:00.002642 At every minute
...
Run Code Online (Sandbox Code Playgroud)