Python 如何使用argparse获取程序名?

Python 如何使用argparse获取程序名?,python,argparse,Python,Argparse,我正在使用argparse解析命令行参数。在浏览文档时,我只能看到使用不同程序名的规定 我希望能够使用默认程序名,而不必导入sys。据我所知,argparse中没有返回程序名的内容 import argparse parser = argparse.ArgumentParser() args = parser.parse_args() print(dir(args)) 以下是输出: “UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU

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

我希望能够使用默认程序名,而不必导入
sys
。据我所知,
argparse
中没有返回程序名的内容

import argparse

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

print(dir(args))
以下是输出:

“UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU","新","减少","减少","减少","减少","模块","报告","设置属性","大小","结构","子类",__weakref_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


有没有其他方法可以在不必导入
sys
模块的情况下检索程序名?

ArgumentParser
实例有一个
prog
属性,我想这就是您想要的

import argparse

parser = argparse.ArgumentParser()
print('parser.prog: {}'.format(parser.prog))
我是通过在中阅读模块的源代码发现这一点的,特别是查看
类ArgumentParser
。由于属性的名称不以下划线字符开头,我假设它是公共的

更新

我看到,至少现在,
ArgumentParser
实例的
prog
属性在和中都有文档记录(或自提出此问题以来一直有文档记录)


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

当然正确的方法是:

>>> import sys
>>> print sys.argv[0]
    scripts/script.py
但是让我们假设您有一个很好的理由阻止您导入sys,但允许您导入argparse

在发现
prog
方面做了出色的工作,让我们尝试一下:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> print parser.prog
    script.py
如所述,它只有文件名,而没有完整的路径,如
sys.argv[0]
,因为模块使用的是
prog=os.path.basename(sys.argv[0])

但是
argparse
必须使用
sys
,因此需要在
argparse
命名空间中访问它。让我们检查一下:

>>> import argparse
>>> print argparse.__dict__
    { ..., '_sys': <module 'sys' (built-in)>, ... }
您使用的是
sys
!当然,但我没有导入它,只是
argparse
,这就是问题所在

当然,这有很多禁忌症:

  • 您不应该使用以其他名称空间的
    \uu
    \u
    为前缀的变量,它们会被使用
  • 您不应该依赖其他模块的导入,它们可能会发生变化
  • 您不应该依赖未记录的api,它们可能会更改
太长,读不下去了 这很有趣,但是只要坚持导入sys
,直到
argparse
发布一个api来访问sys.argv[0]
%(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()
然后:

给出:

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
记录于:

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


在Python 3.5.2上测试。

在这种情况下为什么不导入sys?如果需要,可以从sys import argv导入argv。
。我是否错误地认为argparse是sys.argv[]上的包装器模块?因为argparse解析所有的命令行参数,所以它不应该也有更干净的代码的程序名吗?Imho,当sys.argv[0]时,它看起来很奇怪当它在其他地方使用argparse时,会突然与代码冲突。
argparse
sys
导入为
\u sys
。因此理论上可以使用:
argparse.\u sys.argv[0]
。还要注意,
argparse
\u sys.argv[1:]
。另请参见:谢谢您提供的所有详细信息!不过我接受了@martineau的回答,因为它直接回答了我的问题。
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
cd ..
./mydir/main.py