我想在 django 的后台保留一个长进程 运行

I want to keep a long process running in the background in django

我是 django 的初学者。

我想在后台保留 django 中的 运行ning 长进程。

我想保留它 运行ning 除非我明确结束该过程。

我不知道在哪里以及如何将以下代码添加到 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)

我会详细说明我想做什么。

  1. 运行 django 启动时的一个循环。
  2. 在任何给定时间将 long_task 添加到循环中(当特定事件发生时 通过监视外部站点发生)。
  3. 将程序 运行ning 保留在后台以便站点可以访问 看过。将来我想展示这个的结果 页面上的程序。
  4. 在其他时间关闭循环(在维护期间)。

这是我试过的方法

  1. 使用 celery 和 celery-beat 作为任务注册并执行。

=>

无法指定程序在 django 启动时应 运行

  1. 在 django 中创建一个自定义任务并 运行 使用命令。

.

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')

=> 我收到以下错误,但无法 运行。

”django.core.exceptions.SynchronousOnlyOperation:您不能从异步上下文中调用它 - 使用线程或 sync_to_async。”

我也不知道启动django能做什么

  1. 将代码添加到 init.py。

.

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')

=>

我收到以下错误,但无法 运行。

“您不能从异步上下文中调用它 - 使用线程或 sync_to_async。”

--环境--

请告诉我如何做到这一点。

AsyncIO 事件循环不是线程安全的;您不能 运行 来自与最初创建时不同的线程的循环。您的 run_loop 函数应该不带任何参数,并且 create/start 一个新的事件循环到 运行 您的协程:

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)