I have a async function and need to run in with apscheduller every N minutes. There is a python code below
URL_LIST = ['<url1>',
'<url2>',
'<url2>',
]
def demo_async(urls):
"""Fetch list of web pages asynchronously."""
loop = asyncio.get_event_loop() # event loop
future = asyncio.ensure_future(fetch_all(urls)) # tasks to do
loop.run_until_complete(future) # loop until done
async def fetch_all(urls):
tasks = [] # dictionary of start times for each url
async with ClientSession() as session:
for url in urls:
task = asyncio.ensure_future(fetch(url, session))
tasks.append(task) # create list of tasks
_ = await asyncio.gather(*tasks) # gather task responses
async def fetch(url, session):
"""Fetch a url, using specified ClientSession."""
async with session.get(url) as response:
resp = await response.read()
print(resp)
if __name__ == '__main__':
scheduler = AsyncIOScheduler()
scheduler.add_job(demo_async, args=[URL_LIST], trigger='interval', seconds=15)
scheduler.start()
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
# Execution will block here until Ctrl+C (Ctrl+Break on Windows) is pressed.
try:
asyncio.get_event_loop().run_forever()
except (KeyboardInterrupt, SystemExit):
pass
But when i tried to run it i have the next error info
Job "demo_async (trigger: interval[0:00:15], next run at: 2017-10-12 18:21:12 +04)" raised an exception.....
..........\lib\asyncio\events.py", line 584, in get_event_loop
% threading.current_thread().name)
RuntimeError: There is no current event loop in thread '<concurrent.futures.thread.ThreadPoolExecutor object at 0x0356B150>_0'.
Could you please help me with this? Python 3.6, APScheduler 3.3.1,
Just pass
fetch_all
toscheduler.add_job()
directly. The asyncio scheduler supports coroutine functions as job targets.If the target callable is not a coroutine function, it will be run in a worker thread (due to historical reasons), hence the exception.
In your
def demo_async(urls)
, try to replace:with:
The important thing that hasn't been mentioned is why the error occurs. For me personally, knowing why the error occurs is as important as solving the actual problem.
Let's take a look at the implementation of the
get_event_loop
ofBaseDefaultEventLoopPolicy
:You can see that the
self.set_event_loop(self.new_event_loop())
is only executed if all of the below conditions are met:self._local._loop is None
-_local._loop
is not setnot self._local._set_called
-set_event_loop
hasn't been called yetisinstance(threading.current_thread(), threading._MainThread)
- current thread is the main one (this is not True in your case)Therefore the exception is raised, because no loop is set in the current thread:
Use
asyncio.run()
instead of directly using the event loop. It creates a new loop and closes it when finished.This is how the 'run' looks like:
Since this question continues to appear on the first page, I will write my problem and my answer here.
I had a
RuntimeError: There is no current event loop in thread 'Thread-X'.
when using flask-socketio and Bleak.Edit: well, I refactored my file and made a class.
I initialized the loop in the constructor, and now everything is working fine:
Usage:
Original answer:
The solution was stupid. I did not pay attention to what I did, but I moved some
import
out of a function, like this:So I thought that I needed to change something in my code, and I created a new event loop using this piece of code just before the line with
get_event_loop()
:At this moment I was pretty happy, since I had a loop running.
But not responding. And my code relied on a timeout to return some values, so it was pretty bad for my app.
It took me nearly two hours to figure out that the problem was the
import
, and here is my (working) code: