python之參數解析模塊argparse


2.7之后python不再對optparse模塊進行擴展,python標准庫推薦使用argparse模塊對命令行進行解析。

簡單入門

先來看個例子:

argparse_test.py:

import argparse

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

運行程序:

ShanedeMBP:some_work shane$ python3 argparse_test.py --help
usage: argparse_test.py [-h]

optional arguments:
  -h, --help  show this help message and exit
ShanedeMBP:some_work shane$ python3 argparse_test.py --verbose
usage: argparse_test.py [-h]
argparse_test.py: error: unrecognized arguments: --verbose
ShanedeMBP:some_work shane$ python3 argparse_test.py foo
usage: argparse_test.py [-h]
argparse_test.py: error: unrecognized arguments: foo
ShanedeMBP:some_work shane$ 

結果分析:

  • 若不給參數而運行這個程序,將不會得到任何結果。
  • 第二條命名顯示了使用的argparse的好處,你什么也沒做,卻得到了一個很好的幫助信息。
  • 我們無需人為設置--help參數,就能得到一個良好的幫助信息。但是若給其他參數(比如foo)就會產生一個錯誤。

位置參數

我們修改下腳本:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()

運行:

nedeMBP:some_work shane$ python3 argparse_test.py 
usage: argparse_test.py [-h] echo
argparse_test.py: error: the following arguments are required: echo
ShanedeMBP:some_work shane$ python3 argparse_test.py --help
usage: argparse_test.py [-h] echo

positional arguments:
  echo

optional arguments:
  -h, --help  show this help message and exit
ShanedeMBP:some_work shane$ python3 argparse_test.py foo


結果分析:

  • 這次,我們增加了一個add_argument()方法,用來設置程序可接受的命令行參數。
  • 現在要運行程序,就必須設置一個參數。
  • parse_args()方法實際上從我們的命令行參數中返回了一些數據,在上面的例子中是echo
  • 這個像“魔法”一樣的過程,是argparse自動完成的。

盡管自動產生的幫助信息展示地很美觀,但是我們仍然無法只根據echo這個參數知道它是做什么的。所以,我們增加了一些東西,使得它變得更有用。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("echo",help=" echo the string you use here!")
args = parser.parse_args()
# print(args.echo)

運行結果

ShanedeMBP:some_work shane$ python3 argparse_test.py 
usage: argparse_test.py [-h] echo
ShanedeMBP:some_work shane$ python3 argparse_test.py foo
foo
ShanedeMBP:some_work shane$ python3 argparse_test.py -h
usage: argparse_test.py [-h] echo

positional arguments:
  echo        echo the string you use here!

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

再多一點改變:

import argparse

parser = argparse.ArgumentParser()
# parser.add_argument("echo",help=" echo the string you use here!")
parser.add_argument('square',help="input the digital number")
args = parser.parse_args()
print(args.square**2)

輸出結果:

ShanedeMBP:some_work shane$ python3 argparse_test.py 4
Traceback (most recent call last):
  File "argparse_test.py", line 10, in <module>
    print(args.square**2)
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

這個程序並不能正確運行,因為argparse會將輸入當作字符串處理,所以我們需要設置它的類型:(type=int)

import argparse

parser = argparse.ArgumentParser()
# parser.add_argument("echo",help=" echo the string you use here!")
parser.add_argument('square',help="input the digital number",type=int)
args = parser.parse_args()
print(args.square**2)

運行結果:

ShanedeMBP:some_work shane$ python3 argparse_test.py 4
16
ShanedeMBP:some_work shane$ python3 argparse_test.py four
usage: argparse_test.py [-h] square
argparse_test.py: error: argument square: invalid int value: 'four'

這樣,指定了type類型后,可自動識別類型,好方便有木有...

詳解

import argparse

#創建一個解析對象
parser = argparse.ArgumentParser()
# parser.add_argument("echo",help=" echo the string you use here!")
#向對象中添加相關命令行參數或選項,每一個add_argument方法對應一個參數或選項
parser.add_argument('square',help="input the digital number",type=int)
#調用parse_args()方法進行解析
args = parser.parse_args()
print(args.square**2)

方法ArgumentParser

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)

這些參數都有默認值,當調用parser.print_help()或者運行程序時由於參數不正確(此時python解釋器其實也是調用了pring_help()方法)時,會打印這些描述信息,一般只需要傳遞description參數,如上。

prog

程序的名字,默認為sys.argv[0],用來在help信息中描述程序的名稱。

>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.print_help()
usage: myprogram [-h]

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

usage

描述程序用途的字符串

>>> parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]')
>>> parser.add_argument('--foo', nargs='?', help='foo help')
>>> parser.add_argument('bar', nargs='+', help='bar help')
>>> parser.print_help()
usage: PROG [options]

positional arguments:
 bar          bar help

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

description

help信息前的文字。

epilog

help信息之后的信息

>>> parser = argparse.ArgumentParser(
...     description='A foo that bars',
...     epilog="And that's how you'd foo a bar")
>>> parser.print_help()
usage: argparse.py [-h]

A foo that bars

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

And that's how you'd foo a bar

parents

由ArgumentParser對象組成的列表,它們的arguments選項會被包含到新ArgumentParser對象中。

>>> parent_parser = argparse.ArgumentParser(add_help=False)
>>> parent_parser.add_argument('--parent', type=int)

>>> foo_parser = argparse.ArgumentParser(parents=[parent_parser])
>>> foo_parser.add_argument('foo')
>>> foo_parser.parse_args(['--parent', '2', 'XXX'])
Namespace(foo='XXX', parent=2)

formatter_class

help信息輸出的格式.

prefix_chars

參數前綴,默認為'-'

>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
>>> parser.add_argument('+f')
>>> parser.add_argument('++bar')
>>> parser.parse_args('+f X ++bar Y'.split())
Namespace(bar='Y', f='X')

fromfile_prefix_chars

前綴字符,放在文件名之前

>>> with open('args.txt', 'w') as fp:
...    fp.write('-f\nbar')
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('-f')
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
Namespace(f='bar')

當參數過多時,可以將參數放到文件中讀取,例子中parser.parse_args(['-f', 'foo', '@args.txt'])解析時會從文件args.txt讀取,相當於 ['-f', 'foo', '-f', 'bar']。

argument_default

參數的全局默認值。例如,要禁止parse_args時的參數默認添加,我們可以:

>>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar', nargs='?')
>>> parser.parse_args(['--foo', '1', 'BAR'])
Namespace(bar='BAR', foo='1')
>>> parser.parse_args()
Namespace()

當parser.parse_args()時不會自動解析foo和bar了。

conflict_handler

解決沖突的策略,默認情況下沖突會發生錯誤:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo', help='old foo help')
>>> parser.add_argument('--foo', help='new foo help')
Traceback (most recent call last):
 ..
ArgumentError: argument --foo: conflicting option string(s): --foo

我們可以設定沖突解決策略:

>>> parser = argparse.ArgumentParser(prog='PROG', conflict_handler='resolve')
>>> parser.add_argument('-f', '--foo', help='old foo help')
>>> parser.add_argument('--foo', help='new foo help')
>>> parser.print_help()
usage: PROG [-h] [-f FOO] [--foo FOO]

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

add_help

設為False時,help信息里面不再顯示-h --help信息。

方法add_argument 參數選項

add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])
>>> 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)')

name or flags

命令行參數名或者選項,如上面的address或者-p,--port.其中命令行參數如果沒給定,且沒有設置defualt,則出錯。但是如果是選項的話,則設置為None,如果是多個參數(短參數和長參數)表示同一個意義的話,可用,隔開

一共有兩種,位置參數和可選參數.

添加可選參數:

>>> parser.add_argument('-f', '--foo')

添加位置參數:

>>> parser.add_argument('bar')

parse_args()運行時,會用'-'來認證可選參數,剩下的即為位置參數。

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-f', '--foo')
>>> parser.add_argument('bar')
>>> parser.parse_args(['BAR'])
Namespace(bar='BAR', foo=None)
>>> parser.parse_args(['BAR', '--foo', 'FOO'])
Namespace(bar='BAR', foo='FOO')
>>> parser.parse_args(['--foo', 'FOO'])
usage: PROG [-h] [-f FOO] bar
PROG: error: too few arguments

解析時沒有位置參數就會報錯了。

action

默認為store

store_const,值存放在const中:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_const', const=42)
>>> parser.parse_args('--foo'.split())
Namespace(foo=42)

store_true和store_false,值存為True或False:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_true')
>>> parser.add_argument('--bar', action='store_false')
>>> parser.add_argument('--baz', action='store_false')
>>> parser.parse_args('--foo --bar'.split())
Namespace(bar=False, baz=True, foo=True)

append:存為列表

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='append')
>>> parser.parse_args('--foo 1 --foo 2'.split())
Namespace(foo=['1', '2'])

append_const:存為列表,會根據const關鍵參數進行添加:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--str', dest='types', action='append_const', const=str)
>>> parser.add_argument('--int', dest='types', action='append_const', const=int)
>>> parser.parse_args('--str --int'.split())
Namespace(types=[<type 'str'>, <type 'int'>])

count:統計參數出現的次數

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--verbose', '-v', action='count')
>>> parser.parse_args('-vvv'.split())
Namespace(verbose=3)

version:版本

>>> import argparse
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--version', action='version', version='%(prog)s 2.0')
>>> parser.parse_args(['--version'])
PROG 2.0

nargs

命令行參數的個數,一般使用通配符表示,其中,'?'表示只用一個,'*'表示0到多個,'+'表示至少一個

值可以為整數N(N個),*(任意多個),+(一個或更多)

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='*')
>>> parser.add_argument('--bar', nargs='*')
>>> parser.add_argument('baz', nargs='*')
>>> parser.parse_args('a b --foo x y --bar 1 2'.split())
Namespace(bar=['1', '2'], baz=['a', 'b'], foo=['x', 'y'])

值為?時,首先從命令行獲得參數,若沒有則從const獲得,然后從default獲得:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='?', const='c', default='d')
>>> parser.add_argument('bar', nargs='?', default='d')
>>> parser.parse_args('XX --foo YY'.split())
Namespace(bar='XX', foo='YY')
>>> parser.parse_args('XX --foo'.split())
Namespace(bar='XX', foo='c')
>>> parser.parse_args(''.split())
Namespace(bar='d', foo='d')

獲取參數順序:命令行-->const-->default

更常用的情況是允許參數為文件:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'),
...                     default=sys.stdin)
>>> parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
...                     default=sys.stdout)
>>> parser.parse_args(['input.txt', 'output.txt'])
Namespace(infile=<open file 'input.txt', mode 'r' at 0x...>,
          outfile=<open file 'output.txt', mode 'w' at 0x...>)
>>> parser.parse_args([])
Namespace(infile=<open file '<stdin>', mode 'r' at 0x...>,
          outfile=<open file '<stdout>', mode 'w' at 0x...>)

const

保存一個常量

default

默認值,上面剛介紹過

choices

可供選擇的值

>>> parser = argparse.ArgumentParser(prog='doors.py')
>>> parser.add_argument('door', type=int, choices=range(1, 4))
>>> print(parser.parse_args(['3']))
Namespace(door=3)
>>> parser.parse_args(['4'])
usage: doors.py [-h] {1,2,3}
doors.py: error: argument door: invalid choice: 4 (choose from 1, 2, 3)

type

參數的類型,默認是字符串string類型,還有float、int等類型

required

是否必選

desk

可作為參數名

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', dest='bar')
>>> parser.parse_args('--foo XXX'.split())
Namespace(bar='XXX')

help

和ArgumentParser方法中的參數作用相似,出現的場合也一致

解析參數的幾種寫法

最常見的空格分開:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
>>> parser.add_argument('--foo')
>>> parser.parse_args('-x X'.split())
Namespace(foo=None, x='X')
>>> parser.parse_args('--foo FOO'.split())
Namespace(foo='FOO', x=None)

長選項用=分開

>>> parser.parse_args('--foo=FOO'.split())
Namespace(foo='FOO', x=None)

短選項可以寫在一起:

>>> parser.parse_args('-xX'.split())
Namespace(foo=None, x='X')

parse_args()方法的返回值為namespace,可以用vars()內建函數化為字典:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo')
>>> args = parser.parse_args(['--foo', 'BAR'])
>>> vars(args)
{'foo': 'BAR'}

例子

例子1:

import argparse

def parse_args():
    description = usage: %prog [options] poetry-file

This is the Slow Poetry Server, blocking edition.
Run it like this:

  python slowpoetry.py 

If you are in the base directory of the twisted-intro package,
you could run it like this:

  python blocking-server/slowpoetry.py poetry/ecstasy.txt

to serve up John Donne's Ecstasy, which I know you want to do.


    parser = argparse.ArgumentParser(description = description)
    
    help = The addresses to connect.
    parser.add_argument('addresses',nargs = '*',help = help)

    help = The filename to operate on.Default is poetry/ecstasy.txt
    parser.add_argument('filename',help=help)

    help = The port to listen on. Default to a random available port.
    parser.add_argument('-p',--port', type=int, help=help)

    help = The interface to listen on. Default is localhost.
    parser.add_argument('--iface', help=help, default='localhost')

    help = The number of seconds between sending bytes.
    parser.add_argument('--delay', type=float, help=help, default=.7)

    help = The number of bytes to send at a time.
    parser.add_argument('--bytes', type=int, help=help, default=10)

    args = parser.parse_args();
    return args

if __name__ == '__main__':
	args = parse_args()
	
	for address in args.addresses:
		print 'The address is : %s .' % address
	
	print 'The filename is : %s .' % args.filename
	print 'The port is : %d.' % args.port
	print 'The interface is : %s.' % args.iface
	print 'The number of seconds between sending bytes : %f'% args.delay
	print 'The number of bytes to send at a time : %d.' % args.bytes

例子2

有一道面試題:編寫一個腳本main.py,使用方式如下:

main.py -u http://www.sohu.com -d 'a=1,b=2,c=3' -o /tmp/index.html

功能要求:打開-u指定的頁面,將頁面中所有的鏈接后面增加參數a=1&b=2&c=3(需要考慮鏈接中已經存在指定的參數的問題), 然后保存到-o指定的文件中。

import argparse
import urllib
from pyquery import PyQuery as pq
def getArgs():
	parse=argparse.ArgumentParser()
	parse.add_argument('-u',type=str)
	parse.add_argument('-d',type=str)
	parse.add_argument('-o',type=str)
	args=parse.parse_args()
	return vars(args)
def urlAddQuery(url,query):
	query=query.replace(',','&')  
	if '?' in url:
		return url.replace('?','?'+query+'&')
	else:
		return url+'?'+query
def getHref():
	args=getArgs()
	url=args['u']
	query=args['d'].strip("\'")
	fileName=args['o']
	doc=pq(url=url)
	with open(fileName,'w') as f:
		for a in doc('a'):
			a=pq(a)
			href=a.attr('href')
			if href:
				newurl=urlAddQuery(href,query)
				f.write(newurl+'\n')
if __name__=='__main__':
	getHref()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM