Câu trả lời:
Câu trả lời này cho thấy optparse
cái nào phù hợp với các phiên bản Python cũ hơn. Đối với Python 2.7 trở lên, argparse
thay thế optparse
. Xem câu trả lời này để biết thêm thông tin.
Như những người khác đã chỉ ra, bạn nên đi với optparse hơn getopt. getopt gần như là ánh xạ một-một của các hàm thư viện C chuẩn (3) C, và không dễ sử dụng.
optparse, trong khi dài dòng hơn một chút, có cấu trúc tốt hơn và đơn giản hơn để mở rộng sau này.
Đây là một dòng điển hình để thêm một tùy chọn cho trình phân tích cú pháp của bạn:
parser.add_option('-q', '--query',
action="store", dest="query",
help="query string", default="spam")
Nó nói khá nhiều cho chính nó; tại thời điểm xử lý, nó sẽ chấp nhận -q hoặc --query làm tùy chọn, lưu trữ đối số trong một thuộc tính được gọi là truy vấn và có giá trị mặc định nếu bạn không chỉ định nó. Nó cũng tự ghi lại rằng bạn khai báo đối số trợ giúp (sẽ được sử dụng khi chạy với -h / - help) ngay tại đó với tùy chọn.
Thông thường bạn phân tích các đối số của bạn với:
options, args = parser.parse_args()
Theo mặc định, điều này sẽ phân tích các đối số chuẩn được truyền cho tập lệnh (sys.argv [1:])
Options.query sau đó sẽ được đặt thành giá trị bạn chuyển cho tập lệnh.
Bạn tạo một trình phân tích cú pháp đơn giản bằng cách thực hiện
parser = optparse.OptionParser()
Đây là tất cả những điều cơ bản bạn cần. Đây là một kịch bản Python hoàn chỉnh cho thấy điều này:
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
5 dòng trăn cho bạn thấy những điều cơ bản.
Lưu nó trong sample.py và chạy nó một lần với
python sample.py
và một lần với
python sample.py --query myquery
Ngoài ra, bạn sẽ thấy rằng optparse rất dễ mở rộng. Trong một trong các dự án của tôi, tôi đã tạo một lớp Command cho phép bạn lồng các lệnh con trong cây lệnh một cách dễ dàng. Nó sử dụng optparse rất nhiều để xâu chuỗi các lệnh lại với nhau. Đó không phải là thứ tôi có thể dễ dàng giải thích trong một vài dòng, nhưng hãy thoải mái duyệt xung quanh trong kho lưu trữ của tôi cho lớp chính, cũng như một lớp sử dụng nó và trình phân tích cú pháp tùy chọn
-mcProfile -o program.prof
nhưng agrparcer đang nắm bắt các đối số này, làm cách nào để chuyển các đối số này sang python exe ???
argparse
là con đường để đi Dưới đây là một bản tóm tắt ngắn về cách sử dụng nó:
1) Khởi tạo
import argparse
# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')
2) Thêm đối số
# 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')
3) phân tích
args = parser.parse_args()
4) Truy cập
print("Argument values:")
print(args.pos_arg)
print(args.opt_pos_arg)
print(args.opt_arg)
print(args.switch)
5) Kiểm tra giá trị
if args.pos_arg > 10:
parser.error("pos_arg cannot be larger than 10")
Sử dụng đúng:
$ ./app 1 2 --opt_arg 3 --switch
Argument values:
1
2
3
True
Đối số không chính xác:
$ ./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
Trợ giúp đầy đủ:
$ ./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
Từ năm 2012, có một mô-đun rất dễ dàng, mạnh mẽ và thực sự tuyệt vời để phân tích cú pháp đối số được gọi là docopt . Dưới đây là một ví dụ được lấy từ tài liệu của nó:
"""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)
Vì vậy, đây là: 2 dòng mã cộng với chuỗi doc của bạn là điều cần thiết và bạn nhận được các đối số của mình được phân tích cú pháp và có sẵn trong đối tượng đối số của bạn.
Kể từ năm 2017, có một mô-đun thú vị khác gọi là python-fire . Nó có thể tạo giao diện CLI cho mã của bạn khi bạn thực hiện phân tích đối số bằng không . Đây là một ví dụ đơn giản từ tài liệu (chương trình nhỏ này hiển thị hàm double
cho dòng lệnh):
import fire
class Calculator(object):
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
Từ dòng lệnh, bạn có thể chạy:
> calculator.py double 10
20
> calculator.py double --number=15
30
Cách hông mới là argparse
vì những lý do này . argparse> optparse> getopt
cập nhật: Kể từ py2.7 argparse là một phần của thư viện chuẩn và optparse không được dùng nữa.
Tôi thích Click . Nó trừu tượng hóa các tùy chọn quản lý và cho phép "(...) tạo ra các giao diện dòng lệnh đẹp theo cách có thể kết hợp với càng ít mã càng cần thiết".
Đây là ví dụ sử dụng:
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()
Nó cũng tự động tạo các trang trợ giúp được định dạng độc đáo:
$ 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.
Khá nhiều người đang sử dụng getopt
Đây là mã ví dụ cho tài liệu:
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
Vì vậy, trong một từ, đây là cách nó hoạt động.
Bạn có hai loại tùy chọn. Những người đang nhận được tranh luận, và những người giống như các thiết bị chuyển mạch.
sys.argv
là khá nhiều char** argv
trong C. Giống như trong C, bạn bỏ qua phần tử đầu tiên là tên chương trình của bạn và chỉ phân tích các đối số:sys.argv[1:]
Getopt.getopt
sẽ phân tích cú pháp theo quy tắc bạn đưa ra trong đối số.
"ho:v"
ở đây mô tả các đối số ngắn : -ONELETTER
. Có :
nghĩa là -o
chấp nhận một đối số.
Cuối cùng ["help", "output="]
mô tả các đối số dài ( --MORETHANONELETTER
). Đầu =
ra sau một lần nữa có nghĩa là đầu ra chấp nhận một đối số.
Kết quả là một danh sách các cặp vợ chồng (tùy chọn, đối số)
Nếu một tùy chọn không chấp nhận bất kỳ đối số (như --help
ở đây) thìarg
phần đó là một chuỗi rỗng. Sau đó, bạn thường muốn lặp trong danh sách này và kiểm tra tên tùy chọn như trong ví dụ.
Tôi hy vọng điều này đã giúp bạn.
getopt
trong các phiên bản mới hơn của Python, câu trả lời này đã lỗi thời.
getopt
vẫn không bị từ chối Nhưng Nhưng tài liệu của nó nói rằng nó chủ yếu được cung cấp cho người dùng quen với getopt()
chức năng C và thừa nhận rằng đối với những người dùng khác argparse
có thể là một giải pháp tốt hơn, cho phép "viết ít mã hơn và nhận được trợ giúp tốt hơn và thông báo lỗi ".
Sử dụng optparse
đi kèm với thư viện tiêu chuẩn. Ví dụ:
#!/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()
Nguồn: Sử dụng Python để tạo các công cụ dòng lệnh UNIX
Tuy nhiên, đối với Python 2.7 optparse không được dùng nữa, hãy xem: Tại sao nên sử dụng argparse thay vì optparse?
Chỉ trong trường hợp bạn có thể cần, điều này có thể hữu ích nếu bạn cần lấy các đối số unicode trên Win32 (2K, XP, v.v.):
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()
Đối số dòng lệnh nhẹ mặc định
Mặc dù argparse
là tuyệt vời và là câu trả lời đúng cho các chuyển đổi dòng lệnh và các tính năng nâng cao được ghi lại đầy đủ, bạn có thể sử dụng mặc định đối số chức năng để xử lý các đối số vị trí đơn giản rất đơn giản.
import sys
def get_args(name='default', first='a', second=2):
return first, int(second)
first, second = get_args(*sys.argv)
print first, second
Đối số 'name' ghi lại tên tập lệnh và không được sử dụng. Đầu ra thử nghiệm trông như thế này:
> ./test.py
a 2
> ./test.py A
A 2
> ./test.py A 20
A 20
Đối với các tập lệnh đơn giản mà tôi chỉ muốn một số giá trị mặc định, tôi thấy điều này khá đủ. Bạn cũng có thể muốn bao gồm một số kiểu ép buộc trong các giá trị trả về hoặc giá trị dòng lệnh sẽ là các chuỗi.
Tôi thích optparse để có được. Nó rất khai báo: bạn cho nó biết tên của các tùy chọn và hiệu ứng mà chúng nên có (ví dụ: đặt trường boolean) và nó đưa lại cho bạn một từ điển được điền theo thông số kỹ thuật của bạn.
Tôi nghĩ rằng cách tốt nhất cho các dự án lớn hơn là optparse, nhưng nếu bạn đang tìm kiếm một cách dễ dàng, có thể http://werkzeug.pocoo.org/documentation/script là thứ dành cho bạn.
from werkzeug import script
# actions go here
def action_foo(name=""):
"""action foo does foo"""
pass
def action_bar(id=0, title="default title"):
"""action bar does bar"""
pass
if __name__ == '__main__':
script.run()
Vì vậy, về cơ bản mọi chức năng action_ * được hiển thị với dòng lệnh và một thông báo trợ giúp đẹp được tạo miễn phí.
python foo.py
usage: foo.py <action> [<options>]
foo.py --help
actions:
bar:
action bar does bar
--id integer 0
--title string default title
foo:
action foo does foo
--name string
declarative_parser
. Tất nhiên, nếu một người đang làm việc với werkzeug, có thể tốt hơn để giữ lại werkzung.script
. Dù sao, tôi là một fan hâm mộ lớn của cách tiếp cận như vậy.
Mã argparse có thể dài hơn mã thực hiện thực tế!
Đó là một vấn đề tôi gặp phải với hầu hết các tùy chọn phân tích đối số phổ biến là nếu các tham số của bạn chỉ khiêm tốn, mã để ghi lại chúng trở nên lớn không tương xứng với lợi ích mà chúng cung cấp.
Một người mới tương đối với cảnh phân tích đối số (tôi nghĩ) là plac .
Nó làm cho một số sự đánh đổi được thừa nhận với argparse, nhưng sử dụng tài liệu nội tuyến và kết thúc đơn giản xung quanh main()
chức năng chức năng loại:
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)
an ủi xứng đáng được đề cập ở đây. Nó rất dễ sử dụng. Kiểm tra xem nó:
from consoleargs import command
@command
def main(url, name=None):
"""
:param url: Remote URL
:param name: File name
"""
print """Downloading url '%r' into file '%r'""" % (url, name)
if __name__ == '__main__':
main()
Bây giờ trong giao diện điều khiển:
% python demo.py --help
Usage: demo.py URL [OPTIONS]
URL: Remote URL
Options:
--name -n File name
% python demo.py http://www.google.com/
Downloading url ''http://www.google.com/'' into file 'None'
% python demo.py http://www.google.com/ --name=index.html
Downloading url ''http://www.google.com/'' into file ''index.html''
Đây là một phương pháp, không phải là một thư viện, có vẻ như phù hợp với tôi.
Các mục tiêu ở đây là ngắn gọn, mỗi đối số được phân tích cú pháp bởi một dòng duy nhất, dòng đối số để dễ đọc, mã đơn giản và không phụ thuộc vào bất kỳ mô-đun đặc biệt nào (chỉ os + sys), cảnh báo về các đối số bị thiếu hoặc chưa biết một cách duyên dáng , sử dụng vòng lặp for / Range () đơn giản và hoạt động trên python 2.x và 3.x
Hiển thị là hai cờ chuyển đổi (-d, -v) và hai giá trị được điều khiển bởi các đối số (-i xxx và -o xxx).
import os,sys
def HelpAndExit():
print("<<your help output goes here>>")
sys.exit(1)
def Fatal(msg):
sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))
sys.exit(1)
def NextArg(i):
'''Return the next command line argument (if there is one)'''
if ((i+1) >= len(sys.argv)):
Fatal("'%s' expected an argument" % sys.argv[i])
return(1, sys.argv[i+1])
### MAIN
if __name__=='__main__':
verbose = 0
debug = 0
infile = "infile"
outfile = "outfile"
# Parse command line
skip = 0
for i in range(1, len(sys.argv)):
if not skip:
if sys.argv[i][:2] == "-d": debug ^= 1
elif sys.argv[i][:2] == "-v": verbose ^= 1
elif sys.argv[i][:2] == "-i": (skip,infile) = NextArg(i)
elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
elif sys.argv[i][:2] == "-h": HelpAndExit()
elif sys.argv[i][:1] == "-": Fatal("'%s' unknown argument" % sys.argv[i])
else: Fatal("'%s' unexpected" % sys.argv[i])
else: skip = 0
print("%d,%d,%s,%s" % (debug,verbose,infile,outfile))
Mục tiêu của NextArg () là trả về đối số tiếp theo trong khi kiểm tra dữ liệu bị thiếu và 'bỏ qua' bỏ qua vòng lặp khi NextArg () được sử dụng, giữ cho cờ phân tích cú pháp xuống một lớp lót.
Tôi đã mở rộng cách tiếp cận của Erco để cho phép các đối số vị trí cần thiết và cho các đối số tùy chọn. Chúng nên đi trước các đối số -d, -v, v.v.
Các đối số tùy chọn và tùy chọn có thể được truy xuất với PosArg (i) và OptArg (i, mặc định) tương ứng. Khi tìm thấy một đối số tùy chọn, vị trí bắt đầu tìm kiếm các tùy chọn (ví dụ -i) được di chuyển 1 về phía trước để tránh gây tử vong 'bất ngờ'.
import os,sys
def HelpAndExit():
print("<<your help output goes here>>")
sys.exit(1)
def Fatal(msg):
sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))
sys.exit(1)
def NextArg(i):
'''Return the next command line argument (if there is one)'''
if ((i+1) >= len(sys.argv)):
Fatal("'%s' expected an argument" % sys.argv[i])
return(1, sys.argv[i+1])
def PosArg(i):
'''Return positional argument'''
if i >= len(sys.argv):
Fatal("'%s' expected an argument" % sys.argv[i])
return sys.argv[i]
def OptArg(i, default):
'''Return optional argument (if there is one)'''
if i >= len(sys.argv):
Fatal("'%s' expected an argument" % sys.argv[i])
if sys.argv[i][:1] != '-':
return True, sys.argv[i]
else:
return False, default
### MAIN
if __name__=='__main__':
verbose = 0
debug = 0
infile = "infile"
outfile = "outfile"
options_start = 3
# --- Parse two positional parameters ---
n1 = int(PosArg(1))
n2 = int(PosArg(2))
# --- Parse an optional parameters ---
present, a3 = OptArg(3,50)
n3 = int(a3)
options_start += int(present)
# --- Parse rest of command line ---
skip = 0
for i in range(options_start, len(sys.argv)):
if not skip:
if sys.argv[i][:2] == "-d": debug ^= 1
elif sys.argv[i][:2] == "-v": verbose ^= 1
elif sys.argv[i][:2] == "-i": (skip,infile) = NextArg(i)
elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
elif sys.argv[i][:2] == "-h": HelpAndExit()
elif sys.argv[i][:1] == "-": Fatal("'%s' unknown argument" % sys.argv[i])
else: Fatal("'%s' unexpected" % sys.argv[i])
else: skip = 0
print("Number 1 = %d" % n1)
print("Number 2 = %d" % n2)
print("Number 3 = %d" % n3)
print("Debug = %d" % debug)
print("verbose = %d" % verbose)
print("infile = %s" % infile)
print("outfile = %s" % outfile)