跳转到主要内容

文档函数的简单参数解析器

项目描述

argParseFromDoc

一个简单的Python包,用于根据有类型提示和文档的函数创建/更新 argparse ArgumentParser(s)。

内容

安装

  • 选项1. 克隆此仓库
git clone https://github.com/rsanchezgarc/argParseFromDoc.git
cd argParseFromDoc
pip install .
  • 选项2. 使用pip安装
pip install argParseFromDoc

或者如果您想要最新更新

pip install git+https://github.com/rsanchezgarc/argParseFromDoc

快速概览

argParseFromDoc 允许您直接从函数的类型提示和文档字符串创建参数解析器。如果您已经记录了函数,则为主函数创建解析器并调用的最常见用例可以只用两行代码实现

def add(a: int, b: int):
    '''
    @param a: first number. 
    @param b: second number.
    '''
    return a + b
    
if __name__ == "__main__":
    from argParseFromDoc import parse_function_and_call
    out = parse_function_and_call(add)
    print(out)

argParseFromDoc 还通过 AutoArgumentParser 类和 get_parser_from_function 函数支持更高级的功能。更多详细信息请见下文

支持的功能

以下功能目前受支持

  • 函数参数类型
    • int, str, floatbool
    • (同构)任意前述类型的列表(定义为typing.List[primitive_type]
    • 文件(定义为typing.TextIOtyping.BinaryIO
  • 忽略/选择函数参数的子集
    • 使用 myarg:typing.Optional[VALID_TYPE]=None 将其设置为非必需参数或 args_optional=["myarg"]
  • 创建新的解析器或向其中添加新参数。您还可以使用解析器组
  • 几种文档字符串格式(见 docstring_parser
  • 支持方法定义中假设第一个参数是 self

假设

  • 位置参数。函数可以有位置参数,但解析器会将它们视为关键字/可选参数(总是 --argname VALUE
  • 如果函数签名中某个参数没有提供默认值,则该参数被视为必需的(parser.add_argument(..., required=True))。同样适用于 default=None,除非参数名称包含在 args_optional 中或声明为 typing.Optional
    例如 get_parser_from_function(..., args_optional=[name1, name2...])
  • 布尔参数
    • 布尔参数必须提供默认值。
    • 如果布尔参数默认为 False(name:bool=False),则如果提供了 --name 标志,解析器将参数设置为 name=True
    • 如果布尔参数默认为 True(name:bool=True),则如果提供了 --NOT_name 标志,解析器将参数设置为 name=False。请注意,参数解析器中的参数名称已从 name 更改为 --NOT_name 以反映这一点,但参数使用原始名称存储,因此不需要在代码中进行进一步更改
  • 如果使用 typing.List,则可以提供多个参数。例如:def fun(several_strings: List[str]):
  • 不建议为 typing.TextIOtyping.BinaryIO 设置默认值,因为它们应该是打开的文件。如果您仅使用该函数进行参数解析,则可以将其默认为指向文件的字符串值,但再次强调,这不被鼓励。相反,如果您想设置默认文件名,请使用类型 str。在解析器中,typing.TextIOtyping.BinaryIO 的主要目的是允许管道。例如
    #These two commands are equivalent
    python count_lines --inputFile /etc/passwd 
    cat /etc/passwd | python count_lines --inputFile -
    
    
  • 支持方法,包括 __init__,前提是在定义中使用 self 作为第一个参数
  • 定义函数时,解析器会忽略 *arg**kwargs。不支持其他 *** 参数。

使用方法

您只需使用 typing 记录您函数参数的类型和可能的默认值,并在文档字符串中添加每个参数的说明。记录函数的示例

def add(a: int, b: int):
    '''
    @param a: first number. Mandatory
    @param b: second number. Mandatory
    '''
    return a + b
    
def printYourAge(age: int, name: str = "Unknown"):
    '''
    @param age: your age
    @param name: your name. This is optional
    '''
    return str(a) + " "+ b
    
def addList(several_nums: List[int], b: int=1):
    '''
    @param several_nums: first number
    @param b: second number
    '''
    return [a + b for a in several_nums]

然后,为这些函数中的任何一个(例如 add)获取 ArgumentParser 就像这样简单

if __name__ == "__main__":
    from argParseFromDoc import get_parser_from_function
    parser = get_parser_from_function(add)
    args = parser.parse_args()
    print(add(**vars(args)))

或者您可以直接使用 AutoArgumentParser 类

if __name__ == "__main__":
    from argParseFromDoc import AutoArgumentParser
    parser = AutoArgumentParser()
    parser.add_args_from_function(add)

最后,为了方便,您可以使用一行代码创建解析器,解析参数并调用函数

if __name__ == "__main__":
    from argParseFromDoc import parse_function_and_call
    out = parse_function_and_call(add)

如果您想将函数的参数添加到先前实例化的解析器中,只需将原始解析器(或组)提供给 get_parser_from_function 函数即可。

if __name__ == "__main__":
    from argParseFromDoc import get_parser_from_function
    #standard ArgumentParser
    from argparse import ArgumentParser
    parser = ArgumentParser(prog="Add_example")
    parser.add_argument("--other_type_of_argument", type=str, default="Not provided")
    #####################################################
    # ### If you prefer a group instead of a whole parser
    # group = parser.add_argument_group()
    # get_parser_from_function(add, parser=group)
    #####################################################
    #provide the original parser to get_parser_from_function that will add the new options to the parser
    get_parser_from_function(add, parser=parser)
    args = parser.parse_args()
    print(add(**vars(args)))

最后,如果您的函数有一些您不想包含在解析器中的参数,您可以使用 args_to_ignore 选项。如果您只想使用子集,请使用 args_to_include 选项。

def manyArgsFun(a: int, b: int, c: int = 1, d: int = 2, e: str = "oneStr"):
    '''

    :param a: a
    :param b: b
    :param c: c
    :param d: d
    :param e: e
    :return:
    '''
    print(e)
    return sum([a, b, c, d])


if __name__ == "__main__":
    from argParseFromDoc import get_parser_from_function
    # parser = get_parser_from_function(manyArgsFun, args_to_ignore=["c", "d", "e"])
    parser = get_parser_from_function(manyArgsFun, args_to_include=["a", "b"])
    args = parser.parse_args()
    print(manyArgsFun(**vars(args)))

您可以使用 argParseFromDoc 与子解析器轻松地一起使用。例如

if __name__ == "__main__":
    from argParseFromDoc import AutoArgumentParser, get_parser_from_function
    parser = AutoArgumentParser("programName")

    subparsers = parser.add_subparsers(help='command: this is to select a command', required=True, dest='command')
    
    parser1 = subparsers.add_parser('command1_name', help='')
    get_parser_from_function(function1, parser=parser1)

    parser2 = subparsers.add_parser('command2_name', help='')
    get_parser_from_function(function2, parser=parser2)

    arguments = parser.parse_args()
    if arguments.command == "command1_name":
        del arguments.command
        function1(**vars(arguments))
    elif arguments.command == "command2_name":
        del arguments.command
        function2(**vars(arguments))
    else:
        raise ValueError(f"Command not valid {arguments.command}")

一些额外的示例可以在 examples 文件夹 或在 test_argParseFromDoc.py 中找到

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。

源分布

argParseFromDoc-0.1.2.tar.gz (17.7 kB 查看哈希值)

上传时间 源代码

构建分发版

argParseFromDoc-0.1.2-py3-none-any.whl (20.2 kB 查看哈希值)

上传时间 Python 3

支持者