如何使用argparse获取程序名称?
我正在使用 argparse
来解析命令行参数。在查看 argparse
的文档时,我发现它只提供了使用不同程序名称的选项。
我希望能够使用默认的程序名称,而不需要导入 sys
模块。根据我所看到的,argparse
中似乎没有任何方法可以返回程序名称。
import argparse
parser = argparse.ArgumentParser()
args = parser.parse_args()
print(dir(args))
这是输出结果:
['__class__', '__contains__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_get_args', '_get_kwargs']
有没有其他方法可以获取程序名称,而不需要导入 sys
模块呢?
3 个回答
%(prog)
在 argparse
帮助文本中的使用
这是一个常见的用法,当你想在帮助信息中给出如何使用命令的示例时,就可以用到它。
main.py
#!/usr/bin/env python3
import argparse
parser = argparse.ArgumentParser(
description="Do something cool. My name is: %(prog)s",
epilog="""
This is how you do it:
%(prog)s yourarg
""",
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('somearg', help='also works here: %(prog)s')
args = parser.parse_args()
然后:
./main.py -h
输出为:
usage: main.py [-h] somearg
Do something cool. My name is: main.py
positional arguments:
somearg also works here: main.py
optional arguments:
-h, --help show this help message and exit
This is how you do it:
main.py yourarg
相比于 sys.argv[0]
,一个优点是无论你从哪里调用,它的信息都不会改变:
cd ..
./mydir/main.py
详细信息请查看: https://docs.python.org/3/library/argparse.html#prog
请注意,无论是从
sys.argv[0]
还是通过prog=
参数确定的程序名称,都可以通过%(prog)s
格式符在帮助信息中使用。
在 Python 3.5.2 上测试过。
当然,正确的方法是:
>>> import sys
>>> print sys.argv[0]
scripts/script.py
但假设你有一个很好的理由,导致你不能使用 import sys
,但可以使用 import argparse
。
martineau 找到了一个很棒的方法来获取 prog
,我们来试试:
>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> print parser.prog
script.py
正如 hpaulj 所提到的,这里只得到了文件名,而不是像 sys.argv[0]
那样的完整路径,因为模块 argparse.py
使用了 prog = os.path.basename(sys.argv[0])
。
但是 argparse
必须使用 sys
,所以它需要在 argparse
的命名空间中可访问。我们来检查一下:
>>> import argparse
>>> print argparse.__dict__
{ ..., '_sys': <module 'sys' (built-in)>, ... }
看!我们来试试使用 _sys
:
>>> import argparse
>>> print argparse._sys.argv[0]
scripts/script.py
你正在使用 sys
!当然,但我并没有导入它,只导入了 argparse
,这就是问题所在!
当然,这样做有一些不好的地方:
- 你不应该使用其他命名空间中以
_
或__
开头的变量,因为它们是 内部使用的。 - 你不应该依赖其他模块的导入,因为它们可能会改变。
- 你不应该依赖未记录的 API,因为它们也可能会改变。
总结
这很有趣,但还是老老实实用 import sys
,直到 argparse
发布一个可以访问 sys.argv[0]
的 API。
ArgumentParser
实例有一个叫 prog
的属性,我觉得这就是你想要的东西。
import argparse
parser = argparse.ArgumentParser()
print('parser.prog: {}'.format(parser.prog))
我发现这个是通过查看这个模块的源代码,具体是在 Lib/argparse.py
文件中,特别是看 class ArgumentParser
的 定义。因为这个属性的名字前面没有下划线,我猜它是公开的。
更新
我看到,现在至少在 ArgumentParser
实例的 prog
属性在 Python 2 的文档 和 Python 3 的文档 中都有说明。
所以,是的,这个属性肯定是公开的。在这两个版本中,如果在创建 ArgumentParser
时没有作为关键字参数提供它,它的默认值是 prog = _os.path.basename(_sys.argv[0])
(这里的 _os
和 _sys
是 argparse
模块的私有属性,对应它们没有下划线的版本。需要注意的是,由于使用了 os.basename()
,这个值只会是脚本的文件名,而不是它的完整路径,这个完整路径可能在 sys.argv[0]
中,但这取决于操作系统)。