Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python websocket运行异步函数,但返回错误:无法从正在运行的事件循环调用asyncio.run()_Python_Django_Python 3.x_Django Channels - Fatal编程技术网

Python websocket运行异步函数,但返回错误:无法从正在运行的事件循环调用asyncio.run()

Python websocket运行异步函数,但返回错误:无法从正在运行的事件循环调用asyncio.run(),python,django,python-3.x,django-channels,Python,Django,Python 3.x,Django Channels,我正在尝试使用django Channel 2创建WebSocket。我需要运行一个异步方法,该方法应该返回命令的输出,这样我就可以将数据传递回我网站上的用户。我的问题是,它不允许我运行它,结果出现错误: asyncio.run() cannot be called from a running event loop 我做错了什么?我能做些什么 消费者.py class ChatConsumer(AsyncConsumer): async def websocket_connect(

我正在尝试使用django Channel 2创建WebSocket。我需要运行一个异步方法,该方法应该返回命令的输出,这样我就可以将数据传递回我网站上的用户。我的问题是,它不允许我运行它,结果出现错误:

asyncio.run() cannot be called from a running event loop
我做错了什么?我能做些什么

消费者.py

class ChatConsumer(AsyncConsumer):

    async def websocket_connect(self, event):
        await self.send({
            "type": "websocket.accept"
        })

        user = self.scope['user']
        get_task_id = self.scope['url_route']['kwargs']['task_id']

        await asyncio.run(self.run("golemcli tasks show {}".format(get_task_id)))

        await self.send({
            "type": "websocket.send",
            "text": "hey"
        })
    async def websocket_receive(self, event):
        print("receive", event)

    async def websocket_disconnect(self, event):
        print("disconnected", event)



    async def run(self, cmd):
        proc = await asyncio.create_subprocess_shell(
        cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

        stdout, stderr = await proc.communicate()

        print(f'[{cmd!r} exited with {proc.returncode}]')
        if stdout:
            print(f'[stdout]\n{stdout.decode()}')
        if stderr:
            print(f'[stderr]\n{stderr.decode()}')
回溯:

Exception inside application: asyncio.run() cannot be called from a running event loop
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/sessions.py", line 183, in __call__
    return await self.inner(receive, self.send)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/middleware.py", line 41, in coroutine_call
    await inner_instance(receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/consumer.py", line 62, in __call__
    await await_many_dispatch([receive], self.dispatch)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/utils.py", line 52, in await_many_dispatch
    await dispatch(result)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/consumer.py", line 73, in dispatch
    await handler(message)
  File "/Users/golemgrid/Documents/GitHub/GolemGrid/overview/consumers.py", line 19, in websocket_connect
    await asyncio.run(self.run("golemcli tasks show {}".format(get_task_id)))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/runners.py", line 34, in run
    "asyncio.run() cannot be called from a running event loop")
  asyncio.run() cannot be called from a running event loop
更新2 使用以下代码段时:

await self.run("golemcli tasks show {}".format(get_task_id)
它返回以下回溯:

Exception inside application: Cannot add child handler, the child watcher does not have a loop attached
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/sessions.py", line 183, in __call__
    return await self.inner(receive, self.send)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/middleware.py", line 41, in coroutine_call
    await inner_instance(receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/consumer.py", line 62, in __call__
    await await_many_dispatch([receive], self.dispatch)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/utils.py", line 52, in await_many_dispatch
    await dispatch(result)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/consumer.py", line 73, in dispatch
    await handler(message)
  File "/Users/golemgrid/Documents/GitHub/GolemGrid/overview/consumers.py", line 19, in websocket_connect
    await self.run("golemcli tasks show {}".format(get_task_id))
  File "/Users/golemgrid/Documents/GitHub/GolemGrid/overview/consumers.py", line 37, in run
    stderr=asyncio.subprocess.PIPE)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/subprocess.py", line 202, in create_subprocess_shell
    stderr=stderr, **kwds)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1503, in subprocess_shell
    protocol, cmd, True, stdin, stdout, stderr, bufsize, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/unix_events.py", line 193, in _make_subprocess_transport
    self._child_watcher_callback, transp)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/unix_events.py", line 924, in add_child_handler
    "Cannot add child handler, "
  Cannot add child handler, the child watcher does not have a loop attached

您已经在一个异步运行循环中,因此根据您想要执行的操作,您可以选择

在使用者运行循环中处理
run
调用 (由于存在错误,需要python 3.8)

wait self.run(“golemcli tasks show{}.format(get_task_id))
无需嵌套运行循环

这意味着,如果在
子流程
执行其工作时有任何新消息到达使用者,则这些消息将排队等待,直到
子流程
完成后才会执行。(公平地说,这是最简单的解决办法)

这意味着您的
hey
消息将在
run
方法完成后发送

创建嵌套的运行循环 (由于存在错误,需要python 3.8)

如果您希望您的消费者能够在您的
子流程
运行时处理新消息(发送给它)。(这要复杂得多,除非您的websocket连接需要此功能,否则不应该这样做)

async def websocket_connect(self,event):
...
#开始跑步
self.run\u task=asyncio.create\u任务(self.run(…)
...
异步def websocket_接收(自身、事件):
打印(“接收”,事件)
异步def websocket_断开(自,事件):
打印(“断开”,事件)
如果不是self.run_task.done():
#清理我们创建的队列的任务
self.run_task.cancel()
尝试:
#让我们从嵌套循环中获取任何异常
等待self.run\u任务
除取消错误外:
#忽略此错误,因为我们刚刚触发了它
通过
其他:
#从此嵌套循环中抛出任何错误
self.run_task.result()
作为阻止任务运行,但在线程池中运行 将运行更改为同步任务

#2。在自定义线程池中运行:
loop=asyncio.get\u running\u loop()
将concurrent.futures.ThreadPoolExecutor()作为池:
结果=等待循环。在执行器中运行(
pool,self.run,“你的命令”)
打印('自定义线程池',结果)


作为一个单独的安全注意事项,您的代码可以很容易地让某人在您的服务器上运行bash命令,因为您从url中的任务id获取原始字符串。我建议在这里添加一些验证,如果您在数据库中有一个任务条目,使用url值查找数据库中的任务,然后在生成命令时使用记录中的id值,或者,如果这至少是不可能的,请确保任务id具有非常严格的正则表达式验证,以确保它不能包含任何您不期望的字符。

Hi!我尝试了你的两个建议,它返回了与
child…
相同的错误。关于安全性-我将检查用户的输入。当前的代码是一个简化的演示,只是为了看看它是如何工作的,而我正试图弄明白这个异步/websockets的东西。顺便说一句,我用traceback更新了我的帖子。解决这个问题的更好方法是我可以使用芹菜在后台“卸载”任务,然后获得输出吗?关于shell保护,请看一下python文档中的子进程命令,它们提到了保护自己的方法。这是一个实际错误Python本身就是子输出的东西!我升级到3.8.1,解决了这个问题。我现在可以运行
等待asyncio.run(self.run…)
!谢谢你的帮助,马特豪斯!谢谢你的建议。现在,我将使用
等待self.run
并查看在完成我的方法后结果如何。