【问题标题】:RuntimeError: There is no current event loop in thread ... DiscordPy MultiThreadingRuntimeError: There is no current event loop in thread ... DiscordPy MultiThreading
【发布时间】:2020-10-07 08:43:12
【问题描述】:

所以我有一个 python 脚本,我想在其中同时运行多个不和谐机器人。这些由数据库(Firebase)中有多少用户定义。我现在要做的是,我为数据库中的每个用户都有一个循环,它将它添加到一个数组中。然后为该数组中的每个用户启动一个脚本:

def main(user):

        client = discord.Client()

        token = db.child("users").child(user).child("token").get().val()
        print(user + ": " + token)

        applicationId = db.child("users").child(user).child("appid").get().val()

        discordId = user

        @client.event
        async def on_ready():
                print('Online')

        @client.event
        async def on_message(message):
                print(message)
        client.start(token, bot=False)

def testFunction(some_args):
        print(some_args)
        discord_thread = threading.Thread(target=main, args=(some_args,))
        discord_thread.start()

for user in usersArray:
        testFunction(user)

当我启动脚本时,它会一直工作到 client.start 部分。然后我得到每个线程的错误。 错误:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Users\jonah\AppData\Local\Programs\Python\Python37\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Users\jonah\AppData\Local\Programs\Python\Python37\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "discordnotify.py", line 39, in main
    client = discord.Client()
  File "C:\Users\jonah\AppData\Local\Programs\Python\Python37\lib\site-packages\discord\client.py", line 206, in __init__
    self.loop = asyncio.get_event_loop() if loop is None else loop
  File "C:\Users\jonah\AppData\Local\Programs\Python\Python37\lib\asyncio\events.py", line 644, in get_event_loop
    % threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'Thread-2'.

有没有人可以帮助我?快把我逼疯了!

【问题讨论】:

    标签: python multithreading discord discord.py


    【解决方案1】:

    您不想在运行多个不和谐机器人时使用线程。您可以查看here 了解更多信息,但我现在可以为您安排。修复如何启动不和谐机器人将对您有很大帮助。

    首先,您必须意识到Client.run 是几个更底层概念的抽象。

    Client.login 登录客户端,然后Client.connect 实际运行处理。这些是协程。

    asyncio 提供了将事物放入事件循环的能力,以便它在有时间的时候工作。

    类似这样的东西,例如

    loop = asyncio.get_event_loop()
    
    async def foo():
      await asyncio.sleep(10)
      loop.close()
    
    loop.create_task(foo())
    loop.run_forever()
    

    如果我们想等待另一个协程发生某些事情,asyncio 也通过 asyncio.Event 的同步方式为我们提供了这个功能。您可以将其视为您正在等待的布尔值:

    e = asyncio.Event()
    loop = asyncio.get_event_loop()
    
    async def foo():
      await e.wait()
      print('we are done waiting...')
      loop.stop()
    
    async def bar():
      await asyncio.sleep(20)
      e.set()
    
    loop.create_task(bar())
    loop.create_task(foo())
    loop.run_forever() # foo will stop this event loop when 'e' is set to true
    loop.close()
    

    使用这个概念,我们可以将其应用于不和谐机器人本身。

    import asyncio
    import discord
    from collections import namedtuple
    
    # First, we must attach an event signalling when the bot has been
    # closed to the client itself so we know when to fully close the event loop.
    
    Entry = namedtuple('Entry', 'client event')
    entries = [
      Entry(client=discord.Client(), event=asyncio.Event()),
      Entry(client=discord.Client(), event=asyncio.Event())
    ]
    
    # Then, we should login to all our clients and wrap the connect call
    # so it knows when to do the actual full closure
    
    loop = asyncio.get_event_loop()
    
    async def login():
      for e in entries:
        await e.client.login()
    
    async def wrapped_connect(entry):
      try:
        await entry.client.connect()
      except Exception as e:
        await entry.client.close()
        print('We got an exception: ', e.__class__.__name__, e)
        entry.event.set()
    
    # actually check if we should close the event loop:
    async def check_close():
      futures = [e.event.wait() for e in entries]
      await asyncio.wait(futures)
    
    # here is when we actually login
    loop.run_until_complete(login())
    
    # now we connect to every client
    for entry in entries:
      loop.create_task(wrapped_connect(entry))
    
    # now we're waiting for all the clients to close
    loop.run_until_complete(check_close())
    
    # finally, we close the event loop
    loop.close()
    
    
    

    【讨论】:

      猜你喜欢
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2023-02-23
      • 2022-10-31
      • 1970-01-01
      • 2021-10-29
      相关资源
      最近更新 更多