解析命令行参数的最佳方法是什么?

kam*_*ens 228 python command-line command-line-arguments

解析Python命令行参数的最简单,简洁,最灵活的方法或库是什么?

And*_*bis 202

其他答案确实提到argparse了新Python的方法,但不提供使用示例.为了完整起见,这里有一个如何使用argparse的简短摘要:

1)初始化

import argparse

# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')
Run Code Online (Sandbox Code Playgroud)

2)添加参数

# Required positional argument
parser.add_argument('pos_arg', type=int,
                    help='A required integer positional argument')

# Optional positional argument
parser.add_argument('opt_pos_arg', type=int, nargs='?',
                    help='An optional integer positional argument')

# Optional argument
parser.add_argument('--opt_arg', type=int,
                    help='An optional integer argument')

# Switch
parser.add_argument('--switch', action='store_true',
                    help='A boolean switch')
Run Code Online (Sandbox Code Playgroud)

3)解析

args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)

4)访问

print("Argument values:")
print(args.pos_arg)
print(args.opt_pos_arg)
print(args.opt_arg)
print(args.switch)
Run Code Online (Sandbox Code Playgroud)

5)检查值

if args.pos_arg > 10:
    parser.error("pos_arg cannot be larger than 10")
Run Code Online (Sandbox Code Playgroud)

用法

正确使用:

$ ./app 1 2 --opt_arg 3 --switch

Argument values:
1
2
3
True
Run Code Online (Sandbox Code Playgroud)

参数不正确:

$ ./app foo 2 --opt_arg 3 --switch
usage: convert [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
app: error: argument pos_arg: invalid int value: 'foo'

$ ./app 11 2 --opt_arg 3
Argument values:
11
2
3
False
usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
convert: error: pos_arg cannot be larger than 10
Run Code Online (Sandbox Code Playgroud)

全力帮助:

$ ./app -h

usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]

Optional app description

positional arguments:
  pos_arg            A required integer positional argument
  opt_pos_arg        An optional integer positional argument

optional arguments:
  -h, --help         show this help message and exit
  --opt_arg OPT_ARG  An optional integer argument
  --switch           A boolean switch
Run Code Online (Sandbox Code Playgroud)

  • 这是非常简洁和有用的,这是官方文档(为方便起见):https://docs.python.org/3/library/argparse.html (7认同)

Tho*_*ele 174

这个答案表明optparse哪个适合旧的Python版本.对于Python 2.7及更高版本,argparse替换optparse.有关更多信息,请参阅此答案.

正如其他人所指出的那样,你最好选择optparse而不是getopt.getopt几乎是标准getopt(3)C库函数的一对一映射,并不是很容易使用.

optparse虽然有点冗长,但结构更好,后期更容易扩展.

这是向解析器添加选项的典型行:

parser.add_option('-q', '--query',
            action="store", dest="query",
            help="query string", default="spam")
Run Code Online (Sandbox Code Playgroud)

它几乎说明了自己; 在处理时,它将接受-q或--query作为选项,将参数存储在名为query的属性中,如果不指定它,则具有默认值.它也是自我记录的,你可以使用该选项声明help参数(在使用-h/ - help运行时将使用它).

通常你用以下方法解析你的参数:

options, args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)

默认情况下,这将解析传递给脚本的标准参数(sys.argv [1:])

然后将options.query设置为您传递给脚本的值.

您只需通过执行即可创建解析器

parser = optparse.OptionParser()
Run Code Online (Sandbox Code Playgroud)

这些都是您需要的基础知识.这是一个完整的Python脚本,显示了这一点:

import optparse

parser = optparse.OptionParser()

parser.add_option('-q', '--query',
    action="store", dest="query",
    help="query string", default="spam")

options, args = parser.parse_args()

print 'Query string:', options.query
Run Code Online (Sandbox Code Playgroud)

5行python,向您展示基础知识.

将其保存在sample.py中,然后运行一次

python sample.py
Run Code Online (Sandbox Code Playgroud)

和一次

python sample.py --query myquery
Run Code Online (Sandbox Code Playgroud)

除此之外,您会发现optparse非常容易扩展.在我的一个项目中,我创建了一个Command类,它允许您轻松地在命令树中嵌套子命令.它大量使用optparse将命令链接在一起.这不是我可以在几行中轻松解释的内容,但可以随意在我的存储库中浏览主类,以及使用它和选项解析器的类

  • 对于python 2.3到2.6,这个答案非常清晰且易于理解.对于python 2.7+,它不是最佳答案,因为argparse现在是标准库的一部分,而optparse已弃用. (9认同)

nde*_*mou 68

使用docopt

自2012年以来,Python有一个非常简单,功能强大且非常的参数解析模块,名为docopt.它适用于Python 2.6到3.5,无需安装(只需复制).以下是从其文档中获取的示例:

"""Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Naval Fate 2.0')
    print(arguments)
Run Code Online (Sandbox Code Playgroud)

所以就是这样:2行代码加上你的doc字符串必不可少的,你可以在你的arguments对象中解析你的参数.我告诉你这很酷,不是我;-)

使用python-fire

自2017年以来,python-fire还有另一个很酷的模块,它可以为您的代码提供CLI接口,同时进行参数解析.这是文档中的一个简单示例(这个小程序将函数公开double给命令行):

import fire

class Calculator(object):

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)
Run Code Online (Sandbox Code Playgroud)

从命令行,您可以运行:

> calculator.py double 10
20
> calculator.py double --number=15
30
Run Code Online (Sandbox Code Playgroud)

太棒了不是吗?

  • 我们对安装有不同的定义 - 我想为未来的读者指出这一点. (8认同)
  • docopt如何“不需要安装”?这是一个python模块,因此必须安装。'ImportError:没有名为docopt的模块' (3认同)
  • @keen它肯定不包含在python中,但你不需要安装它:“你可以将docopt.py文件放入你的项目中——它是独立的”——https://github.com/docopt /docopt (2认同)

Sil*_*eed 37

新的臀部方式是argparse出于这些原因.argparse> optparse> getopt

更新:从py2.7开始,argparse是标准库的一部分,不推荐使用optparse.


sud*_*uda 24

我更喜欢Click.它抽象了管理选项,并允许"(...)以可组合的方式创建漂亮的命令行界面,只需要很少的代码".

以下是示例用法:

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()
Run Code Online (Sandbox Code Playgroud)

它还会自动生成格式良好的帮助页面:

$ python hello.py --help
Usage: hello.py [OPTIONS]

  Simple program that greets NAME for a total of COUNT times.

Options:
  --count INTEGER  Number of greetings.
  --name TEXT      The person to greet.
  --help           Show this message and exit.
Run Code Online (Sandbox Code Playgroud)


ful*_*ton 15

几乎每个人都在使用getopt

以下是doc的示例代码:

import getopt, sys

def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
    except getopt.GetoptError:
        # print help information and exit:
        usage()
        sys.exit(2)
    output = None
    verbose = False
    for o, a in opts:
        if o == "-v":
            verbose = True
        if o in ("-h", "--help"):
            usage()
            sys.exit()
        if o in ("-o", "--output"):
            output = a
Run Code Online (Sandbox Code Playgroud)

总之,这就是它的工作原理.

你有两种选择.那些接受争论的人,以及那些像开关一样的人.

sys.argv几乎是你char** argv的C.在C中你跳过第一个元素,它是你的程序的名称,只解析参数:sys.argv[1:]

Getopt.getopt 会根据你在论证中给出的规则来解析它.

"ho:v"这里描述了简短的论点:-ONELETTER.在:该装置-o接受一个参数.

最后["help", "output="]描述了长参数(--MORETHANONELETTER).在=后输出再次意味着输出接受一个参数.

结果是一对夫妇的名单(选项,参数)

如果选项不接受任何参数(如此--help处),则该arg部分为空字符串.然后,您通常希望循环此列表并测试选项名称,如示例中所示.

我希望这对你有所帮助.

  • 随着新版Python中`getopt`的弃用,这个答案已经过时了. (6认同)

Cor*_*rey 14

使用optparse标准库附带的.例如:

#!/usr/bin/env python
import optparse

def main():
  p = optparse.OptionParser()
  p.add_option('--person', '-p', default="world")
  options, arguments = p.parse_args()
  print 'Hello %s' % options.person

if __name__ == '__main__':
  main()
Run Code Online (Sandbox Code Playgroud)

来源:使用Python创建UNIX命令行工具

但是,不推荐使用Python 2.7 optparse,请参阅:为什么使用argparse而不是optparse?


Sha*_*531 6

为了防止你需要,如果你需要在Win32(2K,XP等)上获取 unicode参数,这可能会有所帮助:


from ctypes import *

def wmain(argc, argv):
    print argc
    for i in argv:
        print i
    return 0

def startup():
    size = c_int()
    ptr = windll.shell32.CommandLineToArgvW(windll.kernel32.GetCommandLineW(), byref(size))
    ref = c_wchar_p * size.value
    raw = ref.from_address(ptr)
    args = [arg for arg in raw]
    windll.kernel32.LocalFree(ptr)
    exit(wmain(len(args), args))
startup()
Run Code Online (Sandbox Code Playgroud)


Sim*_*bbs 6

轻量级命令行参数默认值

虽然argparse很好,并且是完全记录的命令行开关和高级功能的正确答案,但您可以使用函数参数默认值来非常简单地处理直接的位置参数.

import sys

def get_args(name='default', first='a', second=2):
    return first, int(second)

first, second = get_args(*sys.argv)
print first, second
Run Code Online (Sandbox Code Playgroud)

'name'参数捕获脚本名称,不使用.测试输出如下所示:

> ./test.py
a 2
> ./test.py A
A 2
> ./test.py A 20
A 20
Run Code Online (Sandbox Code Playgroud)

对于我只想要一些默认值的简单脚本,我发现这已经足够了.您可能还希望在返回值中包含一些类型强制,或者命令行值都将是字符串.

  • def语句中的引号不匹配. (2认同)

QA *_*ive 6

Argparse 代码可能比实际实现代码更长!

我在最流行的参数解析选项中发现的一个问题是,如果您的参数只是适度的,那么记录它们的代码就会变得与它们提供的好处不成比例地大。

(我认为)参数解析场景的一个相对较新的成员是plac

它与 argparse 进行了一些公认的权衡,但使用内联文档并简单地包装了main()类型函数 function:

def main(excel_file_path: "Path to input training file.",
     excel_sheet_name:"Name of the excel sheet containing training data including columns 'Label' and 'Description'.",
     existing_model_path: "Path to an existing model to refine."=None,
     batch_size_start: "The smallest size of any minibatch."=10.,
     batch_size_stop:  "The largest size of any minibatch."=250.,
     batch_size_step:  "The step for increase in minibatch size."=1.002,
     batch_test_steps: "Flag.  If True, show minibatch steps."=False):
"Train a Spacy (http://spacy.io/) text classification model with gold document and label data until the model nears convergence (LOSS < 0.5)."

    pass # Implementation code goes here!

if __name__ == '__main__':
    import plac; plac.call(main)
Run Code Online (Sandbox Code Playgroud)