Python argparse 的范围是什么?

4
可能这是一个愚蠢的问题,但我似乎无法弄清楚。考虑这个简单的场景:
# file a.py
from b import foo
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-a')
args = parser.parse_args()

# file b.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-b')
args = parser.parse_args()

foo = 1

[提示]#python a.py --help

使用方法:a.py [-h] [-b B]

可选参数: -h,--help 显示此帮助消息并退出 -b B

我不明白的是为什么a.py接受参数“b”而不是“a”。另外,如何仅导入变量而不是整个文件? 'from b import foo' 不应该解决这个问题吗?

编辑: 由于我仍然不知道如何解决我的问题(是否有一种清除Python argparse的方法?),因此我发布了另一个与同一问题相关的问题。


当您导入b时,不想运行的任何内容都需要放入if __name__块中。虽然您可能想在b中定义解析器,但可能不想运行parse_args。在这种情况下,b parse_args遇到了“-h”,并发出了一个sys.exit。没有产生错误的输入将由两个解析器解析。但是,如果您想使用b解析器定义的参数,请考虑导入它,并将其作为a解析器的父级传递。 - hpaulj
2个回答

3

from b import foo大致相当于以下代码:

import b
foo = b.foo
del b

虽然它只是“导入 foo”,但仍然运行 b.py 顶层的所有语句(这对于使 foo 有用是必要的),包括对 parse.parse_args() 的调用。这个调用将打印帮助文本并完全忽略 a.py 中 argparse 调用,因为它们还没有发生。
如果您想让您的模块能够添加参数,您需要将 ArgumentParser 的创建与 parse_args 的调用分开。例如,您可以有一个单独的 args 模块:
# file args.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--common')
...

这段代码将被 a.pyb.py 共同使用:

# file a.py
from b import foo
import args
args.parser.add_argument('-a')

# only actually parse args if we are invoked as main script; mere `import a`
# shouldn't run the parser
if __name__ == '__main__':
    args = parser.parse_args()
    ...

# file b.py
import args
args.parser.add_argument('-b')

foo = 1

谢谢您快速而深入的回答。假设我需要在带有参数的b.py中执行操作,但b.py不是主文件,有没有什么方法可以解决这个问题? - Ofir
在这种情况下,我会在 b.py 中定义一个函数来接收参数并处理它们,然后从主文件调用该函数。 - user4815162342
我仍然不确定如何解决这个问题,因为我的b.py文件依赖于其中一些参数,但您确实回答了我的原始问题。谢谢。 - Ofir
@Ofir b.py 中依赖这些参数的部分应该在一个函数中(或者从主模块调用的函数中)调用。 - user4815162342

1

只有在__main__命名空间中才应该解析命令行参数。为了防止b.py解析参数,将其更改为以下内容:

# file b.py

foo = 1

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('-b')
    args = parser.parse_args()

你应该对a.py做类似的操作。


如果ab都需要独立地向参数解析器添加参数,则这种方法行不通。请注意,在OP的代码中,a.py添加了-a,而b.py添加了-b,OP希望生成的脚本能够接受两者。 - user4815162342
那不是你的问题的一部分,但你仍然可以这样做。在这种情况下,您应该只在__main__中创建ArgumentParser对象,但仍然在每个文件的全局范围内添加参数。 - bogatron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接