使用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"))