【问题标题】:Why doesn't multiple on_message events work?为什么多个 on_message 事件不起作用?
【发布时间】:2018-10-14 08:42:00
【问题描述】:

为什么我不能有多个 on_message 事件?

import discord

client = discord.Client()

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

@client.event
async def on_message(message):
    print("in on_message #1")

@client.event
async def on_message(message):
    print("in on_message #2")

@client.event
async def on_message(message):
    print("in on_message #3")

client.run("TOKEN")

例如,如果我输入了任何不和谐的内容,则始终只有最后一个 on_message 被触发。我怎样才能让这三个都工作?

【问题讨论】:

    标签: python discord discord.py


    【解决方案1】:

    原生 Client 是不可能的

    你只能有一个on_message,如果你有多个,on_message 事件只会调用最后一个。您只需要将您的三个 on_message 组合起来。

    import discord
    
    client = discord.Client()
    
    @client.event
    async def on_message(message):
        print("in on_message #1")
        print("in on_message #2")
        print("in on_message #3")
    
    client.run("TOKEN")
    

    与任何 Python 变量/函数一样(除非装饰器存储了您的函数,@client.event 仅保留最近的回调),如果多个名称相同,则保留最近的名称,而所有其他名称将得到覆盖。

    这是我编写的一个简单示例,旨在让您广泛了解 discord.py 中的事件如何工作(注意:实际代码与此不完全相同,因为它已被重写并显着减少)。

    class Client:
        def event(self, func):               
            if func.__name__ == "on_message":
                self.on_message_handle = func
                return func
    
        def receive_message(self, msg):
            func = getattr(self, "on_message_handle", None)
            if func is not None:
                func(msg)
            else:
                self.process_commands(msg)
    
    client = Client()
    
    @client.event
    def on_message(msg):
        print("in on_message #1")
    
    @client.event
    def on_message(msg):
        print("in on_message #2")
    
    client.receive_message("hello")
    # "in on_message #2"
    

    如您所见,client.event 只保留一个 on_message 实例。


    您可以使用 Bot 实例

    或者,如果您使用 discord.py 的 ext.commands 扩展名,则有一种本地方式可以有多个 on_message 回调。为此,您可以将它们定义为listener。您最多可以拥有一个on_message 事件,以及无限数量的on_message 侦听器。

    from discord.ext import commands
    
    bot = commands.Bot('.')
    
    @bot.event
    async def on_message(msg):
        print("in on_message #1")
        await bot.process_commands(msg)  # so `Command` instances will still get called
    
    
    @bot.listen()
    async def on_message(msg):
        print("in on_message #2")
    
    
    @bot.listen()
    async def on_message(msg):
        print("in on_message #3")
    
    bot.run("TOKEN")
    

    收到消息后,所有on_message #1-3都会被打印出来。

    【讨论】:

      【解决方案2】:

      在python中,函数只是对象。

      >>> def foo():
      ...     print ("hi")
      

      定义了一个名为 foo 的对象,您可以使用 Python shell 来查看它。

      >>> foo
      <function foo at 0x...>
      >>> foo()
      hi
      

      如果您在之后定义新方法,或重新定义变量foo,您将无法访问初始函数。

      >>> foo = "hi"
      >>> foo
      hi
      >>> foo()
      Traceback ...:
          file "<stdin>" ...
      TypeError: 'str' object is not callable
      

      @client.event 装饰器的工作原理是它告诉您的客户端应该将新消息通过管道传输到消息中,如果方法被重新定义,则意味着旧方法丢失了。

      >>> @bot.event
      ... async def on_message(m):
      ...     print(1)
      ...
      >>> bot.on_message(None) # @bot.event makes the bot define it's own method
      1
      >>> @bot.event
      ... async def on_message(m):
      ...     print(2)
      ...
      >>> bot.on_message(None) # bot's own method was redefined.
      2
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-15
        • 1970-01-01
        相关资源
        最近更新 更多