如何从另一个进程调用函数/对象

问题描述 投票:0回答:1

总结问题


我有一个 Flask 服务器(带有端点和套接字事件)和一个 Discord 机器人,它们都是独立工作的,我想并行运行它们,这样我就可以从 Flask 端点触发机器人的功能。

描述你尝试过的东西


对于上下文,这是端点的示例:

@app.route("/submit", methods=["POST"])
async def submit():
    data = request.json
    userid = int(os.getenv("USER_ID"))
    message = f"```Title: {data['title']}\nMessage: {data['message']}```"
    await send_dm(userid, message)
    return data

在自己的包装中

send_dm
看起来像这样

# notice that this is not a method of a function
# nor a decorated function with properties from the discord library
# it just uses an intance of the commands.Bot class
async def send_dm(userid: int, message: str):
    user = await bot.fetch_user(userid)
    channel = await user.create_dm()
    await channel.send(message)

所以要并行运行它们并且能够相互通信我试过:

尝试 1:多处理模块

def main():
    executor = ProcessPoolExecutor(2)
    loop = asyncio.new_event_loop()

    loop.run_in_executor(executor, start_bot)
    loop.run_in_executor(executor, start_server)

    loop.run_forever()

if __name__ == "__main__":
    run()

当提到的端点上的函数执行时,我收到以下错误

AttributeError: '_MissingSentinel' object has no attribute 'is_set' on concurrent tasks

尝试二:线程模块

# make them aware of each other
bot.flask_app = app
app.bot = bot
async def main():
    task = threading.Thread(target=start_bot)
    task.start()
    start_server()

if __name__ == "__main__":
    asyncio.run(main())

这种方法带来两个问题:

  • 首先是运行
    start_bot
    我使用
    .start()
    方法而不是
    .run()
    因为根据 this example
    .run()
    创建了自己的事件池,这将使其无法被其他进程访问,并且
    .start()
    是一个异步函数,所以当运行它时我得到错误:
    RuntimeError: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly.
  • 第二,即使使用
    run.()
    函数,在执行上述端点时也会出现同样的问题。

尝试 3:asyncio 模块

def main():
    executor = ProcessPoolExecutor(2)
    loop = asyncio.new_event_loop()
    boo = loop.run_in_executor(executor, start_bot)
    baa = loop.run_in_executor(executor, start_server)

    loop.run_forever()

if __name__ == "__main__":
    main()

这次我实际上执行了两个进程,但仍然无法从烧瓶端点调用我想要的函数。

我也试过了

await asyncio.gather([start_server(), start_bot()])

但是和尝试 2 一样的问题,我已经升级了 flask[async] 模块,所以这不再是问题了。

显示一些代码


要重现我现在拥有的内容,您可以查看完整的回购协议here只有4个文件这个样本应该足以重现。

from server import socketio, app
from bot import bot
from dotenv import load_dotenv
import os
import asyncio
import threading

env_path = os.path.dirname(__file__) + "/.env"
load_dotenv(env_path)

def start_server():
    socketio.run(app)

def start_bot():
    token = os.getenv("BOT_TOKEN")
    bot.run(token)

async def main():
    # this doesn't achieve what I want and is the main part of the problem
    start_server()
    start_bot()

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("Program exited")

我错过了什么吗?请在评论中指出,我会在编辑中添加它。

python flask discord.py flask-socketio
1个回答
0
投票

这就是

IPC
的发明目的。您可以使用一个 dpy 帮助程序库:https://github.com/MiroslavRosenov/better-ipc

这两个进程彼此无关,因此您应该单独启动它们,而不是将它们合并在一个主进程中。

© www.soinside.com 2019 - 2024. All rights reserved.