使用exec()动态调用异步函数

时间:2017-06-23 17:04:53

标签: python python-3.x python-3.5 python-asyncio discord.py

所以,我正在使用discord.py实现Discord Bot,我正在尝试根据命令动态调用函数。我能够使用exec()测试动态函数调用,但是它们似乎因discord.py所需的异步调用而分崩离析。

所以我试图用这个例子做的就是调用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()处理异步调用。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

而不是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()中的任何内容可能会带来危险,相反,将命令列入白名单会更好,例如使用:

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