Python 和 Ruby 的命令行参数解析

Python

optparse

# Python

from optparse import OptionParser

usage = "here is help messages of the command line tool."
opt_parser = OptionParser(usage)

opt_parser.add_option('-s', '--switch', action='store_false', help='set options as switch')
opt_parser.add_option('-n', '--name', type='string', dest='nickname', help='pass in single name')
opt_parser.add_option("-f", "--filename", metavar="FILE", help="write output to FILE")

test_args = ['-n', 'looking', '-s', '-f', 'outfile.txt']
# python test.py -n looking -s -f outfile.txt
(options, args) = opt_parser.parse_args(test_args)
print(opt_parser.print_help())
print(options)
[root@master python3_learning]# python3 test.py
Usage: here is help messages of the command line tool.

Options:
  -h, --help            show this help message and exit
  -s, --switch          set options as switch
  -n NICKNAME, --name=NICKNAME
                        pass in single name
  -f FILE, --filename=FILE
                        write output to FILE
None
{'switch': False, 'nickname': 'looking', 'filename': 'outfile.txt'}

1. add_option 选项里的 -arg1 和 --arg2 一般是对应的,而且默认会把解析的结果保存到 args2 里边,比如下面例子中的 -f 选项:

opt_parser.add_option("-f", "--filename", metavar="FILE", help="write output to FILE")

最终会以 filename 来保存对应的解析结果: 

{..., 'filename': 'outfile.txt'}

2. 除非你自己指定了具体的 dest='args3',那么它会以 args3 为变量名保存。比如下面例子的 -n 选项:

opt_parser.add_option('-n', '--name', type='string', dest='nickname', help='pass in single name')

最终会以 nickname (而不是 name)来保存对应的解析结果(如果没有 dest='nickname' 选项,则结果会包含 ‘name': 'looking'): 

{..., 'nickname': 'looking', ...}

3. action='store_true' (action='store_false' )表示用户不需给出参数值,该类型定义了将布尔值 true (false) 保存到 dest 指定的变量中,比如下面例子的 -s 选项:

opt_parser.add_option('-s', '--switch', action='store_false', help='set options as switch')

 解析 -s 的结果是(如果选项里没有 -s, 则结果为 'switch': None):

{'switch': False, ...}

4. add_option 选项里的 default 参数用于设置默认值:

opt_parser.add_option("-u", "--user", default="root", help="set user to login")

 如果参数里边没有指定 -u 的值,则解析结果会使用默认的值:

{..., 'user': 'root'}

argparse

据说 argparse 要比 optparse 更强大一些哟。下面例子展示的是多个子解析器的使用方式,细节就不用我多讲啦。

# python
# command.py

import argparse



def run_scan(args):
    print('run_scan', args.p, args.l)


def run_aparser(args):
    print('run_aparser', args.p)


class Command:

    def __init__(self):
        self.parser = argparse.ArgumentParser(description='x2openEuler tool chain')
        self.subparser = self.parser.add_subparsers(description='subcommand parser')
        self.scan_parser = self.subparser.add_parser('scan', help='Migration assessment tool')
        self.aparser = self.subparser.add_parser('collect-conf-info', help='aparser tool')
        self.add_args()
        self.set_func()

    def add_args(self):
        self.parser.add_argument('-v', '--version', action='version', version='0.1.0 beta', help='Display version')
        # add_argument 中参数不加 - 的话表示位置参数,
        self.scan_parser.add_argument('p', help='Specify the path of scan')
        self.scan_parser.add_argument('-l', choices=['auto', 'c', 'python', 'java'], help='Select the language of scan')
        self.aparser.add_argument('p', help='Specify the path of file_dir')

    def set_func(self):
        # python3 command.py scan /root/lukaiyi/ttt/python3-pandas-0.25.3-1.oe1.aarch64.rpm -l python
        self.scan_parser.set_defaults(func=run_scan)
        # python3 command.py collect-conf-info /root/lukaiyi/ttt/test
        self.aparser.set_defaults(func=run_aparser)

    def exec_func(self):
        args = self.parser.parse_args()
        args.func(args)


if __name__ == '__main__':
    Command().exec_func()

后来发现,这个 nargs 真的是太好用啦(其他的目前倒还没仔细研究过),它竟然能够给位置参数设置默认值(很屌的,有点颠覆了我的认知,我原先以为就可选参数是可以设置默认值的)

没设置 nargs 的时候是这样子:

from argparse import ArgumentParser

parser = ArgumentParser(description='Test')
parser.add_argument("command", help="the command to be executed",
                    choices=["dump", "delete", "update", "set"], default="set")
args = parser.parse_args()
print(args.command)
C:\Users\lukaiyi\insight-tool>python test.py delete
delete

C:\Users\lukaiyi\insight-tool>python test.py
usage: test.py [-h] {dump,delete,update,set}
test.py: error: the following arguments are required: command

我本来想的是如果位置参数没写的话,会给我把默认值 set 返回来,结果偏偏不给我面子。

但是加上 nargs='?' 就不一样啦(这个时候位置参数就算没写,也可以直接使用给定的默认值):

nargs='?' 

from argparse import ArgumentParser

parser = ArgumentParser(description='Test')
parser.add_argument("command", help="the command to be executed",
                    choices=["dump", "delete", "update", "set"], nargs='?', default="set")
args = parser.parse_args()
print(args.command)
C:\Users\lukaiyi\insight-tool>python test.py
set

C:\Users\lukaiyi\insight-tool>python test.py delete
delete

C:\Users\lukaiyi\insight-tool>python test.py delete update
usage: test.py [-h] [{dump,delete,update,set}]
test.py: error: unrecognized arguments: update

也有使用 nargs='*'  和 nargs='+'  的,看起来和正则表达式中的 ? * + 比较像(实际上含义也确实比较像)。 

nargs='?' 表示这个位置参数可设置零个一个;nargs='*' 表示这个位置参数可设置零个多个;nargs='+' 表示这个位置参数可设置一或多个。如果还是不清楚的话可以看看下面的例子。

nargs='*'

from argparse import ArgumentParser

parser = ArgumentParser(description='Test')
parser.add_argument("command", help="the command to be executed",
                    choices=["dump", "delete", "update", "set"], nargs='*', default="set")
args = parser.parse_args()
print(args.command)
C:\Users\lukaiyi\insight-tool>python test.py
set

C:\Users\lukaiyi\insight-tool>python test.py delete
['delete']

C:\Users\lukaiyi\insight-tool>python test.py delete update
['delete', 'update']

 nargs='+'

from argparse import ArgumentParser

parser = ArgumentParser(description='Test')
parser.add_argument("command", help="the command to be executed",
                    choices=["dump", "delete", "update", "set"], nargs='+', default="set")
args = parser.parse_args()
print(args.command)
C:\Users\lukaiyi\insight-tool>python test.py
usage: test.py [-h] {dump,delete,update,set} [{dump,delete,update,set} ...]
test.py: error: the following arguments are required: command

C:\Users\lukaiyi\insight-tool>python test.py delete
['delete']

C:\Users\lukaiyi\insight-tool>python test.py delete update
['delete', 'update']

Ruby

ruby 的解析就更简单了,一看便懂,就更不用多说了。

# Ruby
require 'optparse'

options = {}
opt_parser = OptionParser.new do |opts|
  opts.banner = 'here is help messages of the command line tool.'

  opts.separator ''
  opts.separator 'Specific options:'
  opts.separator ''

  options[:switch] = false

  opts.on('-s', '--switch', 'Set options as switch') do
    options[:switch] = true
  end

  opts.on('-n NAME', '--name Name', 'Pass-in single name') do |value|
    options[:name] = value
  end

  opts.on('-a A,B', '--array A,B', Array, 'List of arguments') do |value|
    options[:array] = value
  end

  opts.on_tail('-h', '--help', 'Show this message') do
    puts opts
    exit
  end
end

opt_parser.parse!(ARGV)
puts options.inspect
[root@master ruby_learning]# ./test.rb -h
here is help messages of the command line tool.

Specific options:

    -s, --switch                     Set options as switch
    -n, --name Name                  Pass-in single name
    -a, --array A,B                  List of arguments
    -h, --help                       Show this message

[root@master ruby_learning]# ./test.rb -a hello,world
{:switch=>false, :array=>["hello", "world"]}

[root@master ruby_learning]# ./test.rb -s -a hello,world
{:switch=>true, :array=>["hello", "world"]}

[root@master ruby_learning]# ./test.rb -s -n looking -a hello,world
{:switch=>true, :name=>"looking", :array=>["hello", "world"]}

猜你喜欢

转载自blog.csdn.net/TomorrowAndTuture/article/details/110684666