Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

APScheduler to call an async function

I've been having a heck of a time trying to schedule an async function. My understanding is that the AsyncIOScheduler will let me do just that, but in this particular code block, I'm not getting any joy.

Simply running a basic example works no problem:

from datetime import datetime 
import asyncio
from apscheduler.schedulers.asyncio import AsyncIOScheduler

async def tick():
    print(f"Tick! The async time is {datetime.now()}")

if __name__ == '__main__':
    scheduler = AsyncIOScheduler()
    scheduler.add_job(tick, 'interval', seconds=3)
    scheduler.start()

    try:
        asyncio.get_event_loop().run_forever()
    except (KeyboardInterrupt, SystemExit):
        pass

Produces:

Tick! The async time is 2021-07-01 18:47:43.503460
Tick! The async time is 2021-07-01 18:47:46.500421
Tick! The async time is 2021-07-01 18:47:49.500208
^C%                                               

However my code block is erroring out with various things about callables, and proceeding to tell me that seed was never awaited. It awaits just fine called from main() right before setting up the scheduler, but maybe that's a red herring?

I'm no python expert, so please be somewhat gentle :)

Thanks in advance for any clue.

import asyncio
from apscheduler.schedulers.asyncio import AsyncIOScheduler
import c_seed
import c_logging


client = 'async'
state = 'live'
account = 'spot'

async def main():
    c_logging.logging.info("")
    c,l = await c_seed.init(client,state,account)
    await c_seed.seed(c,l)
    scheduler = AsyncIOScheduler()
    scheduler.add_job(c_seed.seed(c,l), 'interval', seconds=60)
    scheduler.start()

if __name__ == "__main__":
    c_logging.logging.info("")
    asyncio.run(main())
2021-07-01 18:43:59,943 [INFO] <module>: c_client
2021-07-01 18:43:59,944 [INFO] <module>: 
2021-07-01 18:43:59,945 [DEBUG] __init__: Using selector: KqueueSelector
2021-07-01 18:43:59,945 [INFO] main: 
2021-07-01 18:43:59,945 [INFO] init: 
2021-07-01 18:43:59,945 [INFO] create: c_client
2021-07-01 18:43:59,945 [INFO] create: c_client -> async
2021-07-01 18:43:59,945 [INFO] create: c_client -> live
2021-07-01 18:44:00,591 [INFO] pairs_list: 
2021-07-01 18:44:00,753 [DEBUG] seed: async seed start
2021-07-01 18:44:07,040 [DEBUG] seed: async seed complete
Traceback (most recent call last):
  File "/Users/Documents/Development/main.py", line 58, in <module>
    asyncio.run(main()) 
  File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/Users/Documents/Development/main.py", line 36, in main
    scheduler.add_job(c_seed.seed(c,l), 'interval', seconds=60)
  File "/Users/Documents/Development/.venv/lib/python3.8/site-packages/apscheduler/schedulers/base.py", line 439, in add_job
    job = Job(self, **job_kwargs)
  File "/Users/Documents/Development/.venv/lib/python3.8/site-packages/apscheduler/job.py", line 49, in __init__
    self._modify(id=id or uuid4().hex, **kwargs)
  File "/Users/Documents/Development/.venv/lib/python3.8/site-packages/apscheduler/job.py", line 170, in _modify
    raise TypeError('func must be a callable or a textual reference to one')
TypeError: func must be a callable or a textual reference to one
sys:1: RuntimeWarning: coroutine 'seed' was never awaited
like image 856
Jason Avatar asked Feb 02 '26 03:02

Jason


2 Answers

The comment from Paul Cornelius is correct. You have to schedule coroutine functions like any other functions:

scheduler.add_job(c_seed.seed, 'interval', seconds=60, args=(c,l))
like image 67
Alex Grönholm Avatar answered Feb 03 '26 16:02

Alex Grönholm


I was getting a similar error, RuntimeWarning: coroutine 'process_job' was never awaited while using the following code:

async def process_job(job: int):
    await asyncio.sleep(1)
    print(job)

...

scheduler.add_job(lambda: process_job(1), trigger='interval', seconds=5)

In my case I fixed it by using asyncio's run function

from asyncio import run

async def process_job(job: int):
    await asyncio.sleep(1)
    print(job)


scheduler.add_job(lambda: run(process_job(1)), trigger='interval', seconds=5)

Hope this helps.

like image 25
srosser2 Avatar answered Feb 03 '26 16:02

srosser2



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!