0

我对事件循环感到困惑,这可能是一个常见问题,因为似乎人们正在使用 discord.py 和 quart。我正在尝试整合 discord.py、quart 和 celery。

我有一个看起来像这样的 manage.py。它暴露了 app 和 celery,它们分别被 hypercorn 和 celery 使用。我正在尝试让 celery 使用 discord.py 实例

# ./manage.py
from backend import create_app, create_celery
from backend.config import Config

app = create_app()

# celery tasks
celery = create_celery(app)

if __name__ == '__main__':
    app.run(port = 8000)

在 ./backend/init.py 我定义了 create_celery() 和 create_app()

# ./backend/__init__.py
import os
import asyncio
from quart import Quart
from backend.config import Config
from discord.ext import commands
from cogs import MainCog
from celery import Celery
import backend.celeryconfig as celeryconfig


def create_app(script_info=None):
    app = Quart(__name__)
    app.config.from_object(Config)

    # inject discord bot
    @app.before_serving
    async def before_serving(app):
        loop = asyncio.get_event_loop()
        app.discord_bot = commands.Bot(
            command_prefix=">" )
        # add cogs here
        app.discord_bot.add_cog(MainCog(app.discord_bot))

        # connect bot
        await app.discord_bot.login(Config.DISCORD_BOT_TOKEN)
        loop.create_task(app.discord_bot.connect())

    return app

def create_celery(app):
    celery = Celery(
        app.import_name,
        backend=app.config['CELERY_RESULT_BACKEND'],
        broker=app.config['CELERY_BROKER_URL']
    )
    celery.conf.update(app.config)
    celery.config_from_object(celeryconfig)

    class ContextTask(celery.Task):
        def __call__(self, *args, **kwargs):
            async def helper(self, *args, **kwargs):
                async with app.app_context():
                    return await self.run(*args, **kwargs)

            loop = asyncio.get_running_loop() # <-- I'm confused about this
            coroutine = helper(self, *args, **kwargs)
            loop.run_until_complete(coroutine)

    celery.Task = ContextTask
    return celery

当我调用 asyncio.get_running_loop() 时,我没有运行事件循环

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/celery/app/trace.py", line 450, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/app/backend/__init__.py", line 59, in __call__
    loop = asyncio.get_running_loop()
RuntimeError: no running event loop

如何从 celery 的上下文中访问 app.discord_bot?

4

1 回答 1

0

不完全是错误的答案,但另一种方法是使用discord-ext-ipc在 discord.py 和 quart 之间进行 ipc 通信。在这种方法中,增加 ASGI 服务器中的工作人员数量会增加不和谐机器人实例的数量,从而导致不和谐服务器上的重复响应。

https://github.com/Ext-Creators/discord-ext-ipc

于 2021-08-01T19:09:56.210 回答