你如何使用argparse获取程序的名称?

VSN*_*VSN 13 python argparse

argparse用来解析命令行参数.在浏览文档时,argparse我只能看到使用不同程序名称的规定.

我希望能够使用默认程序名称而无需导入sys.argparse根据我的意见,没有任何内容会返回程序名称.

import argparse

parser = argparse.ArgumentParser()
args = parser.parse_args()

print(dir(args))
Run Code Online (Sandbox Code Playgroud)

这是输出:

['__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模块?

mar*_*eau 17

ArgumentParser实例有一个prog我认为你想要的属性.

import argparse

parser = argparse.ArgumentParser()
print('parser.prog: {}'.format(parser.prog))
Run Code Online (Sandbox Code Playgroud)

我通过阅读模块的源代码Lib/argparse.py- 特别是查看class ArgumentParser 定义来发现这一点.由于属性的名称不以下划线字符开头,我认为它是公开的.

更新

我看到,如今至少,该prog属性ArgumentParser的实例(或一直以来这个问题被问)证明无论是在Python 2中的文档Python 3中的文档.

所以,是的,它肯定是公开的,并且在两个版本中,如果它在创建时不作为关键字参数提供ArgumentParser,则默认为prog = _os.path.basename(_sys.argv[0])(where _os_sysprivate私有argparse模块属性对应于非下划线前缀的对应项.请注意,因为使用os.basename(),这只是脚本的文件名,而不是它可能(它依赖于操作系统)的完整路径sys.argv[0].


enr*_*cis 10

当然,正确的方法是:

>>> import sys
>>> print sys.argv[0]
    scripts/script.py
Run Code Online (Sandbox Code Playgroud)

但是,让我们假设你有一个很好的理由阻止你,import sys但允许你import argparse.

马蒂诺做了一个很棒的工作prog,让我们尝试一下:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> print parser.prog
    script.py
Run Code Online (Sandbox Code Playgroud)

正如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)>, ... }
Run Code Online (Sandbox Code Playgroud)

这里是!我们试着用_sys:

>>> import argparse
>>> print argparse._sys.argv[0]
    scripts/script.py
Run Code Online (Sandbox Code Playgroud)

你在用sys!当然,但我还没有进口它argparse,这就是问题所在!

当然,这有许多禁忌症:

  • 您不应使用前缀___其他命名空间的变量,它们在内部使用.
  • 您不应该依赖其他模块的导入,它们可能会发生变化.
  • 你不应该依赖无证的api,它们可能会改变.

TL;博士

这很有趣,但只是坚持import sys,直到argparse发布一个API来访问sys.argv[0].

  • 感谢所有细节!不过,我接受了@ martineau的回答,因为它直接回答了我的问题. (2认同)

Cir*_*四事件 7

%(prog)从内部argparse帮助文本

当您想要举例说明如何在帮助本身中使用该命令时,这是一个常见的用例。

主要.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()
Run Code Online (Sandbox Code Playgroud)

然后:

./main.py -h
Run Code Online (Sandbox Code Playgroud)

给出:

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
Run Code Online (Sandbox Code Playgroud)

一个优点sys.argv[0]是,无论您从何处调用消息,该消息都保持不变:

cd ..
./mydir/main.py
Run Code Online (Sandbox Code Playgroud)

记录于: https: //docs.python.org/3/library/argparse.html#prog

请注意,程序名称,无论是从参数确定sys.argv[0]还是从prog=参数确定,都可用于使用%(prog)s格式说明符的帮助消息。

在 Python 3.5.2 上测试。