使用exec动态调用异步函数()
问题描述:
因此,我正在使用discord.py实现一个Discord Bot,并且我试图根据命令动态调用函数。我能够用exec()很好地测试动态函数调用,但它们似乎与discord.py所需的异步调用分离。使用exec动态调用异步函数()
所以我试图用这个例子来打电话给hello函数,并通过在聊天中输入!hello来打印Hello World进入不一致。
@client.event
async def on_message(message):
call = 'await ' + message.content.lower()[1:] + '(message)'
exec(call)
async def hello(message):
await client.send_message(message.channel, 'Hello World')
不幸的是,这段代码似乎并没有做任何事情,我假设,因为如何执行exec()处理异步调用。任何帮助,将不胜感激。
答
代替exec()
使用globals()
让你的函数:
import asyncio
async def main():
s = "foo"
param = "hello"
coro = globals().get(s)
if coro:
result = await coro(param)
print("got:", result)
else:
print("unknown function:", s)
async def foo(param):
print(param)
await asyncio.sleep(0.11)
return ":-)"
loop = asyncio.get_event_loop()
response = loop.run_until_complete(main())
loop.close()
然而,允许用户访问任何东西globals()
可能BWE危险,相反,它会好得多到白名单的命令,例如使用:
import asyncio
my_commands = {}
def register(cmd):
my_commands[cmd.__name__] = cmd
return cmd
async def main():
s = "foo"
param = "hello"
coro = my_commands.get(s)
if coro:
result = await coro(param)
print("got:", result)
else:
print("unknown function:", s)
@register
async def foo(param):
"""I am the mighty foo command!"""
print(param)
await asyncio.sleep(0.11)
return ":-)"
loop = asyncio.get_event_loop()
response = loop.run_until_complete(main())
loop.close()
参见:
for k, v in my_commands.items():
print("{}: {}".format(k, v.__doc__ or "no docs"))