Jawaban:
Jawaban ini menyarankan optparse
yang sesuai untuk versi Python yang lebih lama. Untuk Python 2.7 dan di atasnya, argparse
gantikan optparse
. Lihat jawaban ini untuk informasi lebih lanjut.
Seperti yang ditunjukkan orang lain, Anda lebih baik menggunakan optparse daripada getopt. getopt cukup banyak pemetaan satu-ke-satu dari fungsi perpustakaan getopt (3) C standar, dan tidak sangat mudah digunakan.
optparse, sementara sedikit lebih bertele-tele, jauh lebih terstruktur dan lebih mudah untuk diperluas nanti.
Inilah garis khas untuk menambahkan opsi ke parser Anda:
parser.add_option('-q', '--query',
action="store", dest="query",
help="query string", default="spam")
Cukup banyak berbicara sendiri; pada waktu pemrosesan, ia akan menerima -q atau --query sebagai opsi, menyimpan argumen dalam atribut yang disebut kueri dan memiliki nilai default jika Anda tidak menentukannya. Ini juga mendokumentasikan diri sendiri ketika Anda mendeklarasikan argumen bantuan (yang akan digunakan saat dijalankan dengan -h / - help) di sana dengan opsi.
Biasanya Anda mengurai argumen Anda dengan:
options, args = parser.parse_args()
Ini akan, secara default, mem-parsing argumen standar yang diteruskan ke skrip (sys.argv [1:])
options.query kemudian akan diatur ke nilai yang Anda berikan ke skrip.
Anda membuat parser hanya dengan melakukan
parser = optparse.OptionParser()
Ini semua dasar-dasar yang Anda butuhkan. Berikut skrip Python lengkap yang menunjukkan ini:
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 baris python yang menunjukkan dasar-dasar.
Simpan di sample.py, dan jalankan sekali dengan
python sample.py
dan sekali dengan
python sample.py --query myquery
Di luar itu, Anda akan menemukan bahwa optparse sangat mudah diperluas. Di salah satu proyek saya, saya membuat kelas Command yang memungkinkan Anda untuk membuat sarang perintah di pohon perintah dengan mudah. Ini menggunakan optparse berat untuk rantai perintah bersama. Ini bukan sesuatu yang bisa saya jelaskan dengan mudah dalam beberapa baris, tetapi merasa bebas untuk menelusuri di repositori saya untuk kelas utama, serta kelas yang menggunakannya dan parser opsi
-mcProfile -o program.prof
tetapi agrparcer menangkap args ini, bagaimana cara meneruskan args ini ke python exe ???
argparse
adalah cara untuk pergi. Berikut ini ringkasan singkat cara menggunakannya:
1) Inisialisasi
import argparse
# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')
2) Tambahkan Argumen
# 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) Parse
args = parser.parse_args()
4) Akses
print("Argument values:")
print(args.pos_arg)
print(args.opt_pos_arg)
print(args.opt_arg)
print(args.switch)
5) Periksa Nilai
if args.pos_arg > 10:
parser.error("pos_arg cannot be larger than 10")
Penggunaan yang benar:
$ ./app 1 2 --opt_arg 3 --switch
Argument values:
1
2
3
True
Argumen yang salah:
$ ./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
Bantuan penuh:
$ ./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
Sejak 2012 ada modul yang sangat mudah, kuat dan sangat keren untuk parsing argumen yang disebut docopt . Berikut ini contoh yang diambil dari dokumentasinya:
"""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)
Jadi ini dia: 2 baris kode ditambah tali doc Anda yang adalah penting dan Anda mendapatkan argumen Anda diurai dan tersedia di objek argumen Anda.
Sejak 2017 ada modul keren lain bernama python-fire . Itu dapat menghasilkan antarmuka CLI untuk kode Anda dengan Anda melakukan parsing argumen nol . Berikut adalah contoh sederhana dari dokumentasi (program kecil ini memperlihatkan fungsi double
ke baris perintah):
import fire
class Calculator(object):
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
Dari baris perintah, Anda dapat menjalankan:
> calculator.py double 10
20
> calculator.py double --number=15
30
Cara pinggul baru adalah argparse
untuk alasan ini . argparse> optparse> getopt
pembaruan: Pada py2.7 argparse adalah bagian dari perpustakaan standar dan optparse sudah tidak digunakan lagi.
Saya lebih suka Klik . Ini mengabstraksi opsi pengelolaan dan memungkinkan "(...) membuat antarmuka baris perintah yang indah dengan cara yang mudah dikompilasi dengan kode sesedikit yang diperlukan".
Berikut contoh penggunaannya:
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()
Itu juga secara otomatis menghasilkan halaman bantuan yang diformat dengan baik:
$ 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.
Cukup banyak orang menggunakan getopt
Berikut ini contoh kode untuk dokumen:
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
Jadi singkatnya, ini dia cara kerjanya.
Anda punya dua jenis opsi. Mereka yang menerima argumen, dan mereka yang seperti switch.
sys.argv
Anda cukup banyak char** argv
di C. Seperti di C Anda melewatkan elemen pertama yang merupakan nama program Anda dan hanya menguraikan argumen:sys.argv[1:]
Getopt.getopt
akan menguraikannya sesuai dengan aturan yang Anda berikan dalam argumen.
"ho:v"
di sini menggambarkan argumen singkat: -ONELETTER
. Cara :
yang -o
menerima satu argumen.
Akhirnya ["help", "output="]
menjelaskan argumen panjang ( --MORETHANONELETTER
). The =
setelah keluaran sekali lagi berarti output yang menerima satu argumen.
Hasilnya adalah daftar pasangan (opsi, argumen)
Jika suatu opsi tidak menerima argumen apa pun (seperti di --help
sini) arg
bagian tersebut adalah string kosong. Anda kemudian biasanya ingin mengulang daftar ini dan menguji nama opsi seperti pada contoh.
Saya harap ini membantu Anda.
getopt
versi Python yang lebih baru, jawaban ini sudah kedaluwarsa.
getopt
masih belum usang ... Tetapi dokumentasinya menyatakan bahwa ini terutama disediakan untuk pengguna yang akrab dengan getopt()
fungsi C , dan mengakui bahwa bagi pengguna lain argparse
mungkin merupakan solusi yang lebih baik, memungkinkan untuk "menulis lebih sedikit kode dan mendapatkan bantuan yang lebih baik dan pesan kesalahan ".
Gunakan optparse
yang datang dengan perpustakaan standar. Sebagai contoh:
#!/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()
Sumber: Menggunakan Python untuk membuat alat baris perintah UNIX
Namun pada Python 2.7 optparse sudah usang, lihat: Mengapa menggunakan argparse daripada optparse?
Jika Anda perlu, ini dapat membantu jika Anda perlu mengambil argumen unicode di Win32 (2K, XP dll):
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()
Argumen baris perintah ringan
Meskipun argparse
hebat dan merupakan jawaban yang tepat untuk sakelar baris perintah yang sepenuhnya didokumentasikan dan fitur-fitur canggih, Anda dapat menggunakan default argumen fungsi untuk menangani argumen posisi langsung dengan sangat sederhana.
import sys
def get_args(name='default', first='a', second=2):
return first, int(second)
first, second = get_args(*sys.argv)
print first, second
Argumen 'nama' menangkap nama skrip dan tidak digunakan. Hasil tes terlihat seperti ini:
> ./test.py
a 2
> ./test.py A
A 2
> ./test.py A 20
A 20
Untuk skrip sederhana di mana saya hanya ingin beberapa nilai default, saya menemukan ini cukup memadai. Anda mungkin juga ingin memasukkan beberapa jenis paksaan dalam nilai-nilai kembali atau nilai-nilai baris perintah semua akan menjadi string.
Saya lebih suka optparse daripada getopt. Ini sangat deklaratif: Anda memberi tahu itu nama opsi dan efek yang seharusnya mereka miliki (misalnya, menyetel bidang boolean), dan memberi Anda kamus yang diisi sesuai dengan spesifikasi Anda.
Saya pikir cara terbaik untuk proyek yang lebih besar adalah optparse, tetapi jika Anda mencari cara yang mudah, mungkin http://werkzeug.pocoo.org/documentation/script adalah sesuatu untuk Anda.
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()
Jadi pada dasarnya setiap fungsi action_ * terpapar ke baris perintah dan pesan bantuan yang bagus dihasilkan secara gratis.
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
. Tentu saja, jika seseorang bekerja dengan werkzeug, mungkin lebih baik menyimpannya werkzung.script
. Bagaimanapun, saya penggemar berat pendekatan semacam itu.
Kode argparse bisa lebih lama dari kode implementasi aktual!
Itulah masalah yang saya temukan dengan opsi parsing argumen paling populer adalah bahwa jika parameter Anda hanya sederhana, kode untuk mendokumentasikannya menjadi tidak proporsional besar untuk manfaat yang mereka berikan.
Pendatang baru relatif ke adegan parsing argumen (saya pikir) adalah plac .
Itu membuat beberapa trade-off yang diakui dengan argparse, tetapi menggunakan dokumentasi sebaris dan hanya membungkus main()
fungsi fungsi tipe:
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)
Consoleargs layak disebutkan di sini. Sangat mudah digunakan. Saksikan berikut ini:
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()
Sekarang di konsol:
% 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''
Inilah metode, bukan perpustakaan, yang sepertinya bekerja untuk saya.
Tujuan di sini harus singkat, setiap argumen diurai oleh satu baris, argumen berbaris agar mudah dibaca, kode sederhana dan tidak bergantung pada modul khusus apa pun (hanya os + sys), memperingatkan tentang argumen yang hilang atau tidak dikenal dengan anggun. , gunakan loop sederhana untuk / range (), dan bekerja melintasi python 2.x dan 3.x
Ditampilkan dua flag toggle (-d, -v), dan dua nilai dikontrol oleh argumen (-i xxx dan -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))
Tujuan dari NextArg () adalah untuk mengembalikan argumen berikutnya sambil memeriksa data yang hilang, dan 'lompati' melompati loop ketika NextArg () digunakan, menjaga flag yang diuraikan menjadi satu liner.
Saya memperluas pendekatan Erco untuk memungkinkan argumen posisi yang diperlukan dan untuk argumen opsional. Ini harus mendahului argumen -d, -v dll.
Argumen posisional dan opsional dapat diambil masing-masing dengan PosArg (i) dan OptArg (i, default). Ketika argumen opsional ditemukan, posisi awal pencarian opsi (misalnya -i) digerakkan 1 di depan untuk menghindari menyebabkan fatal 'tidak terduga'.
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)