python - (半)自动生成函数的 argparsers

标签 python decorator argparse

tldnr:给定一个函数,有没有办法根据其签名自动创建一个 ArgumentParser?

我有很多函数想公开给命令行。所以基本上,一个模块:

 def copy(foo, bar, baz):
    ...
 def move(from, to):
    ...
 def unlink(parrot, nomore=True):
    ...

 if __name__ == '__main__':
     argparse stuff

可以像这样从命令行调用:

 python commands.py move spam ham
 python commands.py unlink --parrot Polly

虽然这实现起来非常简单,但涉及很多布线:

parser = argparse.ArgumentParser(...)
subparsers = parser.add_subparsers()
...
c = subparsers.add_parser('unlink', description='Unlink a parrot')
c.add_argument('--parrot', help='parrots name', required=True)
c.add_argument('--nomore', help='this parrot is no more', action='store_true')
...
c = subparsers.add_parser('move', description='Move stuff')
...

等等,对于每个函数。最糟糕的是,如果函数参数发生变化(它们确实发生了变化),则需要手动同步 argparse 内容。

如果函数可以为自己提供 argparse 东西会更好,这样主要代码就像:

parser = argparse.ArgumentParser(...)
subparsers = parser.add_subparsers()

copy.register(subparsers)
move.register(subparsers)
unlink.register(subparsers)
...

我想到了这些:

@args(
    description='Unlink a parrot',
    parrot={'required':True, 'help':'parrots name'},
    nomore={'action': 'store_true', 'help': 'this parrot is no more'}
)
def unlink(parrot, nomore=True):
    ...

我的问题:

  • 有图书馆做这样的事情吗?
  • 如果不能,是否可以编写这样的装饰器,如何编写?
  • 是否有其他/更好的方法来实现我想要的?

更新:

plac似乎是解决方案。以下是如何用 plac 做我想做的事:

命令模块:cmds.py:

import plac

@plac.annotations(
    foo=('the foo thing'),
    bar=('the bar thing'),
    fast=('do a fast copy', 'flag')
)
def copy(foo, bar, fast=False):
    """Copy some foo to bar."""
    pass
        
@plac.annotations(
    parrots=('parrots names'),
    nomore=('these parrots are no more', 'flag'),
    repeat=('repeat n times', 'option', 'r', int)
)
def unlink(nomore=False, repeat=1, *parrots):
    """Unlink some parrots."""
    pass

#more commands...

# export commands so that plac knows about them
commands = 'copy', 'unlink'

这是主要模块:

import plac
import cmds

plac.call(cmds)

如果你问我的话,非常整洁。

最佳答案

我找到的“最少样板”库是 fire (pip install fire)。

为您的示例创建命令行解析器非常简单:

import fire

def copy(foo, bar, baz):
...
def unlink(parrot, nomore=True):
...

if __name__ == '__main__':
    fire.Fire()

这会将您的模块变成“Fire”CLI:

python your_module.py copy sim sala bim

关于python - (半)自动生成函数的 argparsers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13248487/

相关文章:

python pandas 从价格数据帧创建相关矩阵

python - 如何使用适当的输入形状来训练 CNN?

python - 如何使用 Tensorflow 进行分布式预测/推理

python - 类中字典的 getter/setter 的正确用法——防止在设置字典元素时调用 getter

python - 更改嵌套函数装饰器中的值

python - 自修改Python类

python argparse 就像 --home-path

Python 不会在模块中找到变量

Python argparse -h 选项点缀

python - 使用 'argparse' 而不是 sys.argv