使用argparse时使函数可导入

时间:2018-11-05 04:13:33

标签: python argparse

我有以下CLI程序,该程序将两个数字相加:

import argparse

def foo(args):
    print('X + Y:', args.x + args.y)
    return args.x + args.y


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers()

    foo_parser = subparsers.add_parser('foo')
    foo_parser.add_argument('-x', type=int, default=1)
    foo_parser.add_argument('-y', type=int, default=2)
    foo_parser.set_defaults(func=foo)

    parser.add_argument('--debug', action='store_true', default=False)


    args = parser.parse_args()
    args.func(args)

假设现在我希望我的用户也能够导入foo并使用参数xy直接调用它。即我希望foo看起来像这样:

def foo(x, y):
    print('X + Y:', x + y)
    return x + y

我如何适应args.func(args)来处理这个新的foo

2 个答案:

答案 0 :(得分:1)

args.func(**vars(args))的使用并不适合需要导入以及CLI视图的用例

  • 用户导入函数并对其进行调用时,他们期望返回值可用于进一步处理(控制台上未打印任何内容。调用者可以根据获得的结果来决定打印)
  • 使用CLI时,他们希望看到控制台上显示的输出和正确的退出代码(基于返回值的0或1)

理想的方法是将解析/ CLI管理/求和函数分离为单独的函数,并在解析完成后委托处理(以下是示例示例)

from __future__ import print_function # for python2
import argparse

def mysum(x, y=5):
    return x+y

def delegator(input_args):
    func_map = {
        "mysum" : {
            "func" : mysum,
            "args": (input_args.get("x"),),
            "kwargs" : {
                "y" : input_args.get("y")
            },
            "result_renderer": print
         }
    }

    func_data = func_map.get(input_args.get("action_to_perform"))

    func = func_data.get("func")
    args = func_data.get("args")
    kwargs = func_data.get("kwargs")
    renderer = func_data.get("result_renderer")

    renderer(func(*args, **kwargs))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest="action_to_perform")

    foo_parser = subparsers.add_parser('mysum')
    foo_parser.add_argument('-x', metavar='PATH', type=int, default=1)
    foo_parser.add_argument('-y', metavar='PATH', type=int, default=3)
    delegator(vars(parser.parse_args()))

上述示例还将从您的原始函数中删除* args,** kwargs,并允许委托者根据命令仅发送该函数所需的内容

您可以扩展它以支持多个命令
希望这会有所帮助!

答案 1 :(得分:0)

这是我到目前为止发现的最干净的方法:

import argparse

def foo(*, x, y, **kwargs):
    print('X + Y:', x + y)
    return x + y

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers()

    foo_parser = subparsers.add_parser('foo')
    foo_parser.add_argument('-x', metavar='PATH', type=int, default=1)
    foo_parser.add_argument('-y', metavar='PATH', type=int, default=2)
    foo_parser.set_defaults(func=foo)

    parser.add_argument('--debug', action='store_true', default=False)

    args = parser.parse_args()
    args.func(**vars(args))

也许其他人可以找到更好的东西。