Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.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 asyncio循环。在discord.py不工作的情况下运行_直到_complete()?_Python_Python 3.x_Python Asyncio_Discord_Discord.py - Fatal编程技术网

调用python asyncio循环。在discord.py不工作的情况下运行_直到_complete()?

调用python asyncio循环。在discord.py不工作的情况下运行_直到_complete()?,python,python-3.x,python-asyncio,discord,discord.py,Python,Python 3.x,Python Asyncio,Discord,Discord.py,使用Discord.py制作Discord机器人,这是我第一次使用asyncio,可能也是我第一次在Python中遇到如此令人沮丧的事情 这个问题的重点不是教我如何使用asyncio,而是教我如何避免使用它,即使它不是正确的方法。 因此,我需要从常规的def函数运行discord客户机协程。经过数小时的搜索,我找到了以下内容:asyncio.get\u event\u loop()。运行\u直到完成(…)。我设置了一个小脚本来测试它: import asyncio async def test

使用Discord.py制作Discord机器人,这是我第一次使用asyncio,可能也是我第一次在Python中遇到如此令人沮丧的事情

这个问题的重点不是教我如何使用asyncio,而是教我如何避免使用它,即使它不是正确的方法。

因此,我需要从常规的
def
函数运行discord客户机协程。经过数小时的搜索,我找到了以下内容:
asyncio.get\u event\u loop()。运行\u直到完成(…)
。我设置了一个小脚本来测试它:

import asyncio

async def test():
    print('Success')

asyncio.get_event_loop().run_until_complete(test())
它工作得很好。所以我继续尝试在discord机器人中使用它:

import discord
import asyncio

client = discord.Client()

@client.event
async def on_ready():
    test()

def test():
    asyncio.get_event_loop().run_until_complete(run())

async def run():
    print('Success')

client.run('TOKEN_HERE')
我犯了个错误。。。堆栈跟踪/输出:

Success
Ignoring exception in on_ready
Traceback (most recent call last):
  File "C:\Program Files\Python36\lib\site-packages\discord\client.py", line 307, in _run_event
    yield from getattr(self, event)(*args, **kwargs)
  File "C:/Users/OverclockedSanic/PyCharm Projects/asyncio test/test.py", line 8, in on_ready
    test()
  File "C:/Users/OverclockedSanic/PyCharm Projects/asyncio test/test.py", line 11, in test
    asyncio.get_event_loop().run_until_complete(run())
  File "C:\Program Files\Python36\lib\asyncio\base_events.py", line 454, in run_until_complete
    self.run_forever()
  File "C:\Program Files\Python36\lib\asyncio\base_events.py", line 408, in run_forever
    raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running
奇怪的是结尾的“成功”部分。。。我尝试了一些其他的测试,看看是否可以从协同程序返回数据或执行更多的东西,但它不能

我甚至尝试用
client.loop
替换
asyncio.get\u event\u loop()
,但也没有成功

我找了两天,仍然没有解决办法。有什么想法吗

编辑:
get\u event\u loop()
替换为
new\u event\u loop()

Ignoring exception in on_ready
Traceback (most recent call last):
  File "C:\Program Files\Python36\lib\site-packages\discord\client.py", line 307, in _run_event
    yield from getattr(self, event)(*args, **kwargs)
  File "C:/Users/USER/PyCharm Projects/asyncio test/test.py", line 8, in on_ready
    test()
  File "C:/Users/USER/PyCharm Projects/asyncio test/test.py", line 11, in test
    asyncio.new_event_loop().run_until_complete(run())
  File "C:\Program Files\Python36\lib\asyncio\base_events.py", line 454, in run_until_complete
    self.run_forever()
  File "C:\Program Files\Python36\lib\asyncio\base_events.py", line 411, in run_forever
    'Cannot run the event loop while another loop is running')
RuntimeError: Cannot run the event loop while another loop is running

您的问题似乎本质上是关于混合同步和异步代码。有两种可能性:

1) 如果您的非异步例程不需要阻塞,只需计划一些异步任务(例如,
send\u message
)稍后运行,那么它们只需调用
get\u event\u loop()。create\u task()
。如果希望在异步操作完成时调用其他(非异步)例程,甚至可以对返回的任务使用
add\u done\u callback
。(如果要运行的例程也是非异步的,则使用
get\u event\u loop()。调用\u soon()

2) 如果非异步例程绝对必须阻塞(可能包括等待异步例程),并且不能为以后安排阻塞操作,那么不应该从与主事件循环相同的线程运行它们。您可以使用
concurrent.futures.ThreadPoolExecutor
创建线程池,并使用
asyncio.run\in\u executor()
调度非异步例程,然后等待结果。如果它们反过来需要调用异步例程,那么
运行直到完成()
应该可以工作,因为现在您不是在已经有事件循环的线程中运行。(但要注意线程安全性问题。如果需要等待在主事件循环中运行某些内容,则可能需要类似于
运行\u coroutine\u threadsafe
的内容。)


如果有用的话,
asgiref
包中包含的例程可以为您简化这一过程。它们的设计目的略有不同(web服务器),但也可能适合您。当您想从异步例程调用非异步例程(将在线程池中运行该例程)时,可以使用
wait asgiref.sync.sync\u to_async(func)(args)
,然后使用
asgiref.sync.async\u to_sync(func)(args)
当您想从线程池中运行的非异步例程调用异步例程时。

查看。需要注意的重要一点是,您不必直接处理事件循环,
discord.py
模块将为您解决这个问题。我发现唯一有趣的事情是background\u task.py,即使这样也没有多大帮助……如果您不想使
test
成为一个协程,那么可能会重复,您需要在单独的循环中运行代码
asyncio.new\u event\u loop
我已经自己解决了这个问题,并且忘记了这个问题,但这似乎是一个有用的解决方案。@Overclocked Sanic,你能分享你的解决方案吗?