I am a beginner in django.
I want to keep running long processes in django in the background.
And I want to keep it running unless I explicitly end that process.
I can't figure out where and how to add the following code to django.
import threading
import asyncio
class long_task:
def __init__(self):
self.continue_flag = True
async def long_task(self,):
print('long task start...')
i = 0
while self.continue_flag:
print(i)
await asyncio.sleep(3)
i = i+1
def stop(self):
self.continue_flag = False
def run_loop(loop):
asyncio.set_event_loop(loop)
print('main loop start...')
loop.run_forever()
def ask_loop_stop(loop):
print("main loop stop")
loop.call_soon_threadsafe(loop.stop)
loop = asyncio.get_event_loop()
threading.Thread(target=run_loop, args=(loop,)).start()
print('main loop is ready')
long_task_1 = long_task()
asyncio.run_coroutine_threadsafe(long_task_1.long_task(), loop)
I will elaborate on what I want to do.
Here's what I've tried
=>
Can't specify that a program should be run when django starts
.
class Command(BaseCommand):
help = "Start Main Loop"
def add_arguments(self, parser):
parser.add_argument('-i', default=1, type=int, help='UserId')
def handle(self, *args, **options):
id = options['i']
print("UserId:{},".format(id))
loop = asyncio.get_event_loop()
threading.Thread(target=run_loop, args=(loop,)).start()
print('main loop is ready')
=> I get an following error and can't run it.
”django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.”
I also don't know what I can do when I start django.
.
import asyncio
import threading
import time
from app import long_task
loop = asyncio.get_event_loop()
threading.Thread(target=long_task.run_loop, args=(loop,)).start()
print('main loop is ready')
=>
I get an following error and can't run it.
”You cannot call this from an async context - use a thread or sync_to_async.”
--Environment--
Please tell me how to make this happen.
AsyncIO event loops are not thread safe; you can't run the loop from a different thread than it was originally created on. Your run_loop
function should instead take no arguments, and create/start a new event loop to run your coroutine:
LOOP = None
def run_loop():
global LOOP
LOOP = asyncio.new_event_loop()
LOOP.run_until_complete(long_running_task())
threading.Thread(target=run_loop).start()
# <do other things>
LOOP.call_soon_threadsafe(LOOP.stop)