【问题标题】:I want to keep a long process running in the background in django我想在 django 的后台保持一个很长的进程运行
【发布时间】:2021-08-20 03:54:13
【问题描述】:

我是 django 的初学者。

我想在后台继续在 django 中运行长进程。

除非我明确结束该过程,否则我希望它继续运行。

我不知道在哪里以及如何将以下代码添加到 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. 保持程序在后台运行,以便网站可以 看过。将来我想展示这个结果 页面上的程序。
  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。”

--环境--

  • Windows10 64 位
  • Python (3.7)
  • Redis 服务器 (3.0.504)
  • Django (3.2.3)
  • 芹菜 (5.0.5)
  • django-celery-beat (2.2.0)
  • django-celery-results (2.0.1)
  • PostgreSQL (13)

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

【问题讨论】:

    标签: python django celery python-asyncio python-multithreading


    【解决方案1】:

    AsyncIO 事件循环不是线程安全的;您不能从与最初创建的线程不同的线程运行循环。你的 run_loop 函数应该不带参数,并创建/启动一个新的事件循环来运行你的协程:

    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)
    

    【讨论】:

    • 你是个天才。我能够做我想做的事。您的解释帮助我了解了问题的原因。你能在这么短的时间内阅读我糟糕的解释并给出准确的答案,真是太神奇了。我在这个问题上花费了很多时间。你能够在瞬间解决这个问题。我很佩服你。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多