Python中的參數傳遞與解析 原

Python傳遞命令行參數

Python的命令行參數傳遞和C語言類似,都會把命令行參數保存到argv的變量中。對於python而言,argv是sys模塊中定義的一個list。與C語言不同的是,python中並沒有定義argc,要獲得參數的個數,需要使用len(sys.argv)

當用戶使用'python -c "command" '來運行一條python語句時,argv中保存的是['-c']及"command"後面的參數,例如:

$ python -c 'import sys
print sys.argv' hello world
['-c', 'hello', 'world']

當用戶使用'python -m "module" '來運行一個模塊時,argv中保存的是模塊名及"module"後面的參數,例如:

$ python -m 'show_args' hello world
['/home/kelvin/tmp/show_args.py', 'hello', 'world']

當運行python腳本時,argv中保存的是腳本名及其後面的參數:

$ python show_args.py hello world
['show_args.py', 'hello', 'world']
length of argv: 3

$ cat show_args.py 
#!/bin/env python

import sys

print sys.argv
print "length of argv: " + str(len(sys.argv))

使用標準庫getopt解析選項和參數

getopt模塊和C語言中的getopt函數有着一樣的API,熟悉C語言的同學可快速上手。

# -*- coding: utf-8 -*-
#!/bin/env python

import getopt
import sys


def usage():
    print("Usage:")
    print(sys.argv[0] + ' -i input_file -o output_file')


def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "ho:i:", ["help", "output=", "input="])
    except getopt.GetoptError as err:
        # print help information and exit:
        print("[" + err.opt + "]" + err.msg)
        usage()
        sys.exit(2)
    output = None
    input = None
    for o, a in opts:
        if o in ("-i", "--input"):
            input = a
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-o", "--output"):
            output = a
        else:
            assert False, "unhandled option"
    print("Input file: %s" % (input))
    print("Output file: %s" % (output))

if __name__ == "__main__":
    main()

getopt需要傳入3個參數:

1.  需要解析的字符串,即sys.argv[1:]

2. 短選項集合。其中跟冒號的短選項需要後接參數,如'o:'表示'-o'選項需要接參數。

3. 長選項列表。其中跟等號的長選項需要後接參數。

getopt返回一個元組,元組包括兩個列表opts和args。opts的元素是一個元組,保存瞭解析好的選項和參數對。args保存了除去所有選項和選項的參數之外,剩下的所有參數。

如果解析出錯則會拋出GetoptError異常,該異常有一個參數err。err.opt是出錯時正在解析的選項,err.msg是錯誤消息。

出錯的情況包括:

1. 選項沒有在傳入參數中的短選項或者長選項列表定義。

2. 需要帶參數的選項沒有跟參數。

3. 不需要帶參數的長選項帶了參數。

4. 其他。

kelvin@kvm:~/tmp$ python parse_args.py --help=out
[help]option --help must not have an argument
Usage:
parse_args.py -i input_file -o output_file
kelvin@kvm:~/tmp$ python parse_args.py -i input_file.txt 
Input file: input_file.txt
Output file: None
kelvin@kvm:~/tmp$ python parse_args.py -i input_file.txt --output="hello_world.txt"
Input file: input_file.txt
Output file: hello_world.txt
kelvin@kvm:~/tmp$ python parse_args.py -i input_file.txt -o "output.txt"
Input file: input_file.txt
Output file: output.txt

使用標準庫argparse來解析選項和參數

argparse模塊功能更加強大,例如可以自動生成help文檔等,使用起來也更加簡便,只需要三個步驟即可。第一步,創建一個ArgumentParser對象:

parser = argparse.ArgumentParser(description='Description of the program')

第二步,添加需要解析的選線和參數:

parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the integers (default: find the max)')

第三部,開始解析:

args = parser.parse_args()

ArgumentParser

 class argparse.ArgumentParser(prog=None, usage=None, 
description=None, epilog=None, parents=[], 
formatter_class=argparse.HelpFormatter, prefix_chars='-',
 fromfile_prefix_chars=None, argument_default=None, 
conflict_handler='error', add_help=True, allow_abbrev=True)

常用的參數解釋如下:

prog: 指定程序的名字,默認爲sys.argv[0].

usage: 描述程序該如何使用的字符串,默認會根據添加的參數和選項自動生成

description: 描述程序的功能,默認爲空

epilog: epilog指定的字符串將會顯示在幫助文檔的最後

parents: 一個 ArgumentParser對象的列表,這些對象的選項和參數也會被繼承

add_help: 添加-h/--help選項,默認爲True

allow_abbrev: 允許長選項的縮寫,默認爲True

add_argument

 ArgumentParser.add_argument(name or flags...[, action]
[, nargs][, const][, default][, type][, choices][, required]
[, help][, metavar][, dest])

name將會作爲解析後返回的對象args的屬性,存儲參數的值,flags定義指定的選項,flag的名字也會作爲解析後返回的對象的屬性,存儲該選項的參數。例如:

parser.add_argument('-f', '--foo')
parser.add_argument('arg0')
args = parser.parse_args()
print(args.foo)
print(args.arg0)

執行結果如下:

$./arg_parse.py --foo hello world
hello
world

nargs指定選項參數或者參數本身的個數。例如:

parser.add_argument('-f', '--foo', nargs=2)
args = parser.parse_args()
print(args.foo)

執行結果如下:

$./arg_parse.py --foo hello world
['hello', 'world']

argparse會將--foo選項後面的兩個參數都作爲--foo的參數處理。

action指定argparse如何處理該選項的參數,共有8個值可選。

  1. 'store': 默認值,表示存儲參數,如上面例子中的args.foo存儲hello world.
  2. 'store_const': 存儲常量,常量的值位於const參數中。如:
    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--foo', action='store_const', const=1024)
    args = parser.parse_args()
    print(args.foo)
    
    $ ./arg_parse.py -f
    1024
    

     

  3. 'store_true'或者'store_false':和'store_const'類似,存儲的值爲True或者False

  4. 'append':連個同樣的選項的參數會被放到同一個list裏面,例如:
     

    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--foo', action='append')
    args = parser.parse_args()
    print(args.foo)
    
    $ ./arg_parse.py --foo 1 --foo 2 -f 3
    ['1', '2', '3']

     

  5. 'append_const': 可將多個常量存放到一個list中,選項出現幾次,list中的常量就出現幾次,例如:
     

    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--foo', action='append_const', const="1024")
    args = parser.parse_args()
    print(args.foo)
    
    $ ./arg_parse.py --foo --foo -f
    ['1024', '1024', '1024']

     

  6. 'count':  存儲選項出現的次數。例如:
     

    $ cat arg_parse.py 
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--verbose', action='count')
    args = parser.parse_args()
    print(args.verbose)
    
    $ ./arg_parse.py -vvv
    3
    
    $ ./arg_parse.py -v --verbose -v
    3

     

  7. 'help': 當出現這個選項時,程序打印help文檔然後退出。

  8. 'version': 當出現這個選項時,程序打印版本信息然後退出,版本信息可通過version定義,例如:
     

    $cat arg_parse.py
    #!/usr/bin/env python
    
    import argparse
    
    parser = argparse.ArgumentParser(prog="wchat")
    parser.add_argument('-v', '--version', action='version', version='%(prog)s 3.8.5')
    args = parser.parse_args()
    
    $ ./arg_parse.py --version
    wchat 3.8.5

     

required指定該參數或者選項是必須提供的,否則會報錯退出。

type指定參數的類型,可以是任何python內建的數據類型如int等,也可以是自定義的類型轉換函數的函數名。例如:

$ cat ./arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', type=int)
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -f 12
12

$ ./arg_parse.py -f '12'
12

$ ./arg_parse.py -f hello
usage: arg_parse.py [-h] [-f FOO]
arg_parse.py: error: argument -f/--foo: invalid int value: 'hello'

choices指定一組參數,選項的參數必須從這組參數中來選取。例如:

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', type=int, choices=range(1, 4))
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -f3
3

$ ./arg_parse.py -f19
usage: arg_parse.py [-h] [-f {1,2,3}]
arg_parse.py: error: argument -f/--foo: invalid choice: 19 (choose from 1, 2, 3)

help指定參數或者選項的幫助信息,會出現在help文檔裏。

metavar可以改變幫助文檔中選項的參數佔位字符串,例如,--foo默認的佔位字符串爲FOO,可以通過metavar改爲foo_arg:

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo')
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -h
usage: arg_parse.py [-h] [-f FOO]

optional arguments:
  -h, --help         show this help message and exit
  -f FOO, --foo FOO

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', metavar='foo_arg')
args = parser.parse_args()
print(args.foo)

$ ./arg_parse.py -h
usage: arg_parse.py [-h] [-f foo_arg]

optional arguments:
  -h, --help            show this help message and exit
  -f foo_arg, --foo foo_arg

dest可以修改存儲參數的屬性名,例如:

$ cat arg_parse.py 
#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', dest='bar')
args = parser.parse_args()
print(args.bar)

$ ./arg_parse.py -f hello
hello

小結

getopt雖然提供了接近Unix C的用戶接口,方便了熟悉Unix C的程序猿/媛們,但argparse模塊功能更爲強大,使用起來也更爲簡潔,所以大多數的python項目都採用argparse來解析參數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章