How to convert a string to a function name in python?

前端 未结 9 1989
迷失自我
迷失自我 2020-11-27 12:55

For example, if I have a function called add like

def add(x,y):
    return x+y

and I want the ability to convert a string or a

相关标签:
9条回答
  • 2020-11-27 13:27

    [I got here via a duplicate question. My first thought was to use argparse and shlex and I didn't see that here, so I'm adding it as another option.]

    You could use argparse to set up a registry of functions/commands and safely parse their args. This will provide some level of user-friendliness too by, e.g., letting you know when you've entered a command that doesn't exist.

    import argparse
    import shlex
    
    def hello(name):
        print('hello,', name)
    
    def main():
        parser = argparse.ArgumentParser()
        subparsers = parser.add_subparsers()
    
        hello_parser = subparsers.add_parser('hello')
        hello_parser.add_argument('name')
        hello_parser.set_defaults(func=hello)
    
        print('Enter q to quit')
    
        while True:
            command = input('command> ')
            command = command.strip()
    
            if not command:
                continue
    
            if command.lower() == 'q':
                break
    
            words = shlex.split(command)
    
            try:
                args = parser.parse_args(words)
            except SystemExit:
                # argparse will sys.exit() on -h and errors; prevent that
                continue
    
            func_args = {name: value for name, value in vars(args).items()}
            del func_args['func']
            args.func(**func_args)
    
    if __name__ == '__main__':
        try:
            main()
        except KeyboardInterrupt:
            print()
    
    0 讨论(0)
  • 2020-11-27 13:28

    The built-in function eval will do what you want. All the usual warnings about executing arbitrary user-supplied code apply.

    If there are a finite number of predefined functions, you should avoid eval and use a lookup table instead (i.e. Dict). Never trust your users.

    0 讨论(0)
  • 2020-11-27 13:37

    Since you are taking user input, the safest way is to define exactly what is valid input:

    dispatcher={'add':add}
    w='add'
    try:
        function=dispatcher[w]
    except KeyError:
        raise ValueError('invalid input')
    

    If you want to evaluate strings like 'add(3,4)', you could use safe eval:

    eval('add(3,4)',{'__builtins__':None},dispatcher)
    

    eval in general could be dangerous when applied to user input. The above is safer since __builtins__ is disabled and locals is restricted to dispatcher. Someone cleverer than I might be able to still cause trouble, but I couldn't tell you how to do it.

    WARNING: Even eval(..., {'__builtins__':None}, dispatcher) is unsafe to be applied to user input. A malicious user could run arbitrary functions on your machine if given the opportunity to have his string evaluated by eval.

    0 讨论(0)
提交回复
热议问题