使用该文件中另一个文件中的函数的 Argparse

Posted

技术标签:

【中文标题】使用该文件中另一个文件中的函数的 Argparse【英文标题】:Argparse using function from another file within that file 【发布时间】:2017-08-11 09:10:22 【问题描述】:

我有两个班级:

选项解析器
应用

存储在单独的文件中(option_parser.py 和 application.py)。前者定义了如何处理命令行输入。后者导入前者,读取用户输入,并继续请求。

如何调用在 application.py 的 Application 中定义的方法而不将其导入 option_parser.py(因为这会导致无限循环,因为 application.py 从 option_parser.py 导入 OptionParser)。如果我使用set_defaults(func=method_name),则会被告知全局函数method_name 未在该范围内定义。

我已经有一个解决方法,但它似乎不正确:

if self.options.action == 'tags':
    self.list_tags()
elif self.options.action == 'branches':
    self.list_branches()

我试图在官方文档、Google 和 SO 上找到答案 - 无济于事。

【问题讨论】:

这似乎有什么问题? 这似乎不是正确的解决方案。我希望能够使用:self.options.func() 您能否提供更多上下文 - 这似乎是参数解析和您的类之间非常紧密的耦合,这将使两者都更难测试。 我一直在考虑的另一种解决方法是将代码拆分为三个文件/类:OptionParser、Application 和 Wrapper。 Wrapper 会导入 OptionParser 和 Application,OptionParser 会导入 Application(这样 Application 的方法可以提供给 set_defaults(func=),而 Application 不会导入 OptionParser(而是将类的实例作为参数传递)。这有意义吗? 并非如此。再次,提供更多上下文; edit 对您正在处理的功能进行不太抽象的演示的问题。 【参考方案1】:

我假设您正在使用 set_defaults(func=method_name)argparse 文档中所示的子解析器?这是调用函数的一种简单方法。它利用了在 args 命名空间中定义默认值和设置属性的灵活性。但是没有专门用于此功能的代码。

将函数与此类操作相关联通常是为每个子解析器处理不同操作的最简单方法。但是,如果需要检查被调用的子解析器的名称,add_subparsers() 调用的 dest 关键字参数将起作用:

第二句话是给你使用权限

if self.options.action == 'tags'

在您的情况下,set_defaults 不是最简单的方法。

argparse 主要是一种找出用户想要什么的方法。它并不意味着成为调度员。通常这是你的代码的责任。

我对其他argparse 问题的印象是大多数时候程序员不使用这个set_defaults 选项。在 SO 中搜索 [argparse] set_default 只会找到 37 个帖子(答案或问题)(相比之下,仅 argparse 标签就有 1500 个问题)。


这是一个工作脚本,它实现了我将set_defaults 值传递给parser 设置函数的想法。这是一个文件,但parser 部分也可以导入。

import argparse

def make_parser(defaults):
    parser = argparse.ArgumentParser()
    sp = parser.add_subparsers(dest='cmdstr')
    sp.required = True
    for key in defaults:
        spp = sp.add_parser(key)
        spp.set_defaults(cmd=defaults[key])
    return parser

def foo(args):
    print('foo')

def bar(args):
    print('bar')

if __name__=='__main__':
    dd = 'cmd1': foo, 'cmd2': bar
    parser = make_parser(dd)
    args = parser.parse_args()
    print(args)
    args.cmd(args)

示例调用:

0930:~/mypy$ python3 stack42897689.py cmd1
Namespace(cmd=<function foo at 0xb70c2dac>, cmdstr='cmd1')
foo
0931:~/mypy$ python3 stack42897689.py cmd2
Namespace(cmd=<function bar at 0xb7145614>, cmdstr='cmd2')
bar

有了这个 dd 字典,我可以很容易地完成调度:

dd[args.cmdstr](None)

基本目标是将命令行字符串与函数调用配对。 set_defaults 是在argparse 内进行的一种方式。但是像dd 这样的字典在Python 代码中也被广泛使用。 if/else 语句也是如此。

【讨论】:

好的,谢谢。那么,我想我将不得不满足于“解决方法”的解决方案。 顺便说一句,原因是我想避免使用条件语句块,而是立即调用正确的函数。 您可以通过函数调用参数将函数从主模块传递给导入的模块。我在我的答案中添加了一个粗略的草图。细节需要等待。 嗯,我会考虑的。谢谢你。不确定代码审查员会不会对此皱眉,但这当然值得检查。

以上是关于使用该文件中另一个文件中的函数的 Argparse的主要内容,如果未能解决你的问题,请参考以下文章

你将如何从 Qt 中另一个文件中的函数访问小部件?

Linux中另一个进程的重复文件描述符(没有sendmsg)

argparse 读取 txt 文件

如何通过给定Linux中另一个文件中的列来从文件中删除列?

在excel中另存为宏

访问同一源文件中另一个 .cpp 的成员函数?