python - ¿Por qué no funcionan múltiples eventos on_message?
discord discord.py (2)
¿Por qué no puedo tener múltiples eventos
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")
Por ejemplo, si escribí algo en discordancia, siempre es el último
on_message
que se dispara.
¿Cómo puedo hacer que los tres funcionen?
No es posible con el
Client
nativo.
Solo puede tener
un
on_message
, si tiene varios, solo se llamará al último para el evento
on_message
.
Solo necesitarás combinar tus tres
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")
Como cualquier variable / función de Python (a menos que el decorador almacene su función,
@client.event
hace manteniendo solo la devolución de llamada más reciente), si hay varios nombres iguales, se conservará el más reciente y todos los demás se sobrescribirán.
Este es un ejemplo simple que escribí para brindarle una amplia comprensión de cómo funcionan los eventos en discord.py (nota: el código real no es exactamente así, ya que se reescribió y redujo significativamente).
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"
Como puede ver
client.event
solo mantenga una instancia de
on_message
.
Puedes con instancias de
Bot
Alternativamente, si está utilizando la extensión
ext.commands
de discord.py, existe una forma nativa de tener múltiples
on_message
llamada en
on_message
.
Puedes hacerlo definiéndolos como un
listener
.
Puede tener como máximo un evento
on_message
y una cantidad infinita de oyentes
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")
Cuando se recibe un mensaje, todos los
on_message #1-3
se imprimirán.
En Python, las funciones son solo objetos.
>>> def foo():
... print ("hi")
define un objeto llamado
foo
, puedes ver esto usando un shell de Python.
>>> foo
<function foo at 0x...>
>>> foo()
hi
Si define un nuevo método después de, o redefine la variable
foo
, perderá el acceso a la función inicial.
>>> foo = "hi"
>>> foo
hi
>>> foo()
Traceback ...:
file "<stdin>" ...
TypeError: ''str'' object is not callable
Cómo funciona el decorador de
@client.event
es que le dice a su cliente que los mensajes nuevos deben canalizarse a los mensajes, y bueno, si el método se redefine, significa que el método anterior se ha perdido.
>>> @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