如何将argparse参数作为函数名使用

问题描述 投票:5回答:3

我想实现Argparse介绍中的例子。

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                   help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                   const=sum, default=max,
                   help='sum the integers (default: find the max)')

args = parser.parse_args()
print(args.accumulate(args.integers))

但在我的情况下,我希望有更多的函数名可供选择。

def a(): ...
def b(): ...
def c(): ...

parser.add_argument('-f', '--func', 
                     choices=[a, b, c], 
                     required=True,
                     help="""Choose one of the specified function to be run.""")
parser.func()

这样使用并没有达到预期的效果,我得到的是

$ python program.py -f=a
program.py: error: argument -f/--func: invalid choice: 'a' (choose from 
<function a at 0x7fa15f32f5f0>, 
<function b at 0x7fa15f32faa0>, 
<function c at 0x7ff1967099b0>)

我知道我可以用基本的字符串参数和流控制来解决,但如果能直接使用parser参数作为函数名,就不会那么凌乱,也更容易维护。

python argparse
3个回答
4
投票

您可以使用基本的字符串参数,并通过使用 dict 来从它的名字中获取实际的函数。

我使用的是 Python 2.6.6,所以我不能使用 argparse但这段代码应该能给你一个大致的概念。

#!/usr/bin/env python

def a(): return 'function a'
def b(): return 'function b'
def c(): return 'function c'

func_list = [a, b, c]
func_names = [f.func_name for f in func_list]
funcs_dict = dict(zip(func_names, func_list))

f = funcs_dict['b']
print f()

输出

function b

所以你可以通过 func_namesargparse 并使用以下方法紧凑地检索所需的函数 funcs_dict.


在最新的Python版本中,你应该使用 f.__name__ 而不是 f.func_name. (这在Python 2.6中也能用,但我写这个答案时对新的语法不熟悉)。


3
投票

您需要确保您的 choices 是字符串 (用户不能在命令行中输入 Python 函数对象)。您可以使用字典将这些字符串解析为函数。比如说

# Example functions:
def a(i):
    return i + 1
def b(i):
    return i + 2
def c(i):
    return i + 3

# a dictionary mapping strings of function names to function objects:
funcs = {'a': a, 'b': b, 'c': c}

# Add the -f/--func argument: valid choices are function _names_
parser.add_argument('-f', '--func', dest='func',
                     choices=['a', 'b', 'c'], 
                     required=True,
                     help="""Choose one of the specified function to be run.""")

args = parser.parse_args()

# Resolve the chosen function object using its name:    
chosen_func = funcs[args.func]

2
投票

我的分析,我可能会错,但这是我的理解。

ArgParse允许你通过一个铸造机制从命令行参数中创建更多的简单对象,如果你传递字符串'5'并指定你正在等待一个整数,这让你得到数字5。

而实际上你是想从字符串'a'中得到一个函数。没有铸造的方法可以做到这一点。这是我解决你问题的建议。

import argparse

def foo():
    print("called foo")

def bar():
    print("called bar")

functions = [foo, bar] #list your functions here
functions = { function.__name__ : function for function in functions}

parser = argparse.ArgumentParser()

parser.add_argument('-f', '--func', 
                  choices=list(functions.keys()),
                  required=True,
                  help="""Choose one of the specified function to be run.""")
args = parser.parse_args()
functions[args.func]()

现在你只需要在开始时将你的functons注册到te list函数中,然后在最后一行调用它们,感谢函数索引,并自动替换函数列表。

© www.soinside.com 2019 - 2024. All rights reserved.