Відповіді:
Ця відповідь підказує, optparse
що підходить для старих версій Python. Для Python 2.7 і вище, argparse
замінює optparse
. Дивіться цю відповідь для отримання додаткової інформації.
Як зазначали інші люди, вам краще перейти з оптимізацією над getopt. getopt - це майже однозначне відображення стандартних функцій бібліотеки getopt (3) C, і не дуже просте у використанні.
optparse, хоч і є трохи більш багатослівним, набагато краще структурований і простіший для подальшого продовження.
Ось типовий рядок, щоб додати параметр до свого аналізатора:
parser.add_option('-q', '--query',
action="store", dest="query",
help="query string", default="spam")
Це в значній мірі говорить саме за себе; під час обробки він прийме -q або --query як параметри, збереже аргумент в атрибуті під назвою query і має значення за замовчуванням, якщо ви не вказали його. Це також самодокументування в тому, що ви оголошуєте аргумент довідки (який буде використовуватися при запуску з -h / - help) саме там із опцією.
Зазвичай ви аналізуєте свої аргументи за допомогою:
options, args = parser.parse_args()
Це за замовчуванням буде розбирати стандартні аргументи, передані сценарію (sys.argv [1:])
Потім буде встановлено значення options.query, яке ви передали сценарію.
Ви створюєте аналізатор просто, роблячи це
parser = optparse.OptionParser()
Це всі основи, які вам потрібні. Ось повний сценарій Python, який показує це:
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 рядків пітона, які показують вам основи.
Збережіть його у sample.py та запустіть його один раз
python sample.py
і один раз с
python sample.py --query myquery
Крім того, ви побачите, що оптипар дуже просто розширити. В одному зі своїх проектів я створив клас Command, який дозволяє легко вкладати підкоманди в дерево команд. Він використовує optparse сильно для ланцюга команд разом. Це я не дуже легко поясню в декількох рядках, але не соромтеся переглядати в моєму сховищі основний клас, а також клас, який його використовує, і параметр-аналізатор
-mcProfile -o program.prof
але agrparcer захоплює ці аргументи, як я передаю ці аргументи python exe ???
argparse
це шлях. Ось короткий підсумок того, як ним користуватися:
1) Ініціалізувати
import argparse
# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')
2) Додати аргументи
# 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) Розбір
args = parser.parse_args()
4) доступ
print("Argument values:")
print(args.pos_arg)
print(args.opt_pos_arg)
print(args.opt_arg)
print(args.switch)
5) Перевірте значення
if args.pos_arg > 10:
parser.error("pos_arg cannot be larger than 10")
Правильне використання:
$ ./app 1 2 --opt_arg 3 --switch
Argument values:
1
2
3
True
Неправильні аргументи:
$ ./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
Повна довідка:
$ ./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
З 2012 року існує дуже простий, потужний і дуже класний модуль для розбору аргументів під назвою docopt . Ось приклад, взятий з його документації:
"""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)
Отже, це: 2 рядки коду плюс ваш doc рядок, що є важливим, і ви отримуєте ваші аргументи розібрані та доступні у вашому об'єкті аргументів.
З 2017 року є ще один класний модуль під назвою python-fire . Він може генерувати інтерфейс CLI для вашого коду, коли ви робите нульовий аналіз аргументів. Ось простий приклад з документації (ця невелика програма виставляє функцію double
в командному рядку):
import fire
class Calculator(object):
def double(self, number):
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
З командного рядка можна запустити:
> calculator.py double 10
20
> calculator.py double --number=15
30
Новий спосіб стегна - саме argparse
з цих причин. argparse> optparse> getopt
оновлення: станом на py2.7 argparse є частиною стандартної бібліотеки, а optparse застарілою.
Я віддаю перевагу Клік . Він резюмує керування параметрами та дозволяє "(...) створювати красиві інтерфейси командного рядка компонованим способом з якомога меншим кодом".
Ось приклад використання:
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()
Він також автоматично генерує добре відформатовані довідкові сторінки:
$ 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.
Вже майже всі використовують getopt
Ось приклад коду для документа:
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
Отже, одним словом, ось як це працює.
У вас є два типи варіантів. Ті, хто отримує аргументи, і ті, хто так само, як комутатори.
sys.argv
майже у вашому char** argv
C. Як і в C, ви пропускаєте перший елемент, який є назвою вашої програми, і аналізуєте лише аргументи:sys.argv[1:]
Getopt.getopt
буде аналізувати його відповідно до правила, яке ви наводите в аргументі.
"ho:v"
Тут описані короткі аргументи: -ONELETTER
. В :
означає , що -o
приймає один аргумент.
Нарешті ["help", "output="]
описує довгі аргументи ( --MORETHANONELETTER
). =
Після виведення ще раз означає , що вихід приймає один аргументи.
Результат - список пари (параметр, аргумент)
Якщо параметр не приймає жодного аргументу (наприклад, --help
тут),arg
частина є порожнім рядком. Потім зазвичай потрібно зациклитися на цьому списку і протестувати ім'я параметра, як у прикладі.
Я сподіваюся, що це вам допомогло.
getopt
в нових версіях Python ця відповідь застаріла.
getopt
це ще не застаріло ... Але в його документації зазначено, що він в основному надається користувачам, знайомим з getopt()
функцією C , і визнає, що для інших користувачів argparse
може бути кращим рішенням, що дозволяє "написати менше коду та отримати краща довідка та повідомлення про помилки ".
Використовуйте optparse
стандартну бібліотеку. Наприклад:
#!/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()
Джерело: Використання Python для створення інструментів командного рядка UNIX
Однак, коли Python 2.7 optparse застарілий, див.: Для чого використовувати argparse, а не optparse?
На випадок, якщо вам це знадобиться, це може допомогти, якщо вам потрібно захопити аргументи unicode на Win32 (2K, XP тощо):
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()
Легкі параметри аргументів командного рядка
Хоча argparse
це чудово і є правильною відповіддю для повністю задокументованих комутаторів командного рядка та розширених функцій, ви можете використовувати стандартні параметри аргументів для обробки прямолінійних позиційних аргументів дуже просто.
import sys
def get_args(name='default', first='a', second=2):
return first, int(second)
first, second = get_args(*sys.argv)
print first, second
Аргумент 'name' фіксує ім'я скрипта і не використовується. Тестовий вихід виглядає приблизно так:
> ./test.py
a 2
> ./test.py A
A 2
> ./test.py A 20
A 20
Для простих скриптів, де мені просто потрібні деякі значення за замовчуванням, я вважаю це цілком достатнім. Можливо, ви також хочете включити примусовий тип певного типу у значення повернення або значення командного рядка - всі рядки.
Я віддаю перевагу optparse перед getopt. Це дуже декларативно: ви повідомляєте йому назви параметрів та наслідки, які вони повинні мати (наприклад, встановлення булевого поля), і це повертає вам словник, заповнений відповідно до ваших умов.
Я думаю, що найкращий спосіб для великих проектів - optparse, але якщо ви шукаєте простий спосіб, можливо, http://werkzeug.pocoo.org/documentation/script - це щось для вас.
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()
Тому в основному кожна функція action_ * піддається командному рядку, і приємне повідомлення довідки генерується безкоштовно.
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
. Звичайно, якщо хтось працює з werkzeug, може бути краще зберегти werkzung.script
. У всякому разі, я великий шанувальник такого підходу.
Код Argparse може бути довшим, ніж фактичний код реалізації!
Це проблема, яку я знаходжу в більшості популярних варіантів аналізу аргументів, полягає в тому, що якщо ваші параметри лише скромні, код для їх документування стає непропорційно великим для вигоди, яку вони надають.
Відносно новачок до сцени розбору аргументів (я думаю) - plac .
Він робить визнані компроміси з argparse, але використовує вбудовану документацію і обертається просто навколо main()
функції функції:
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)
консоліарги заслуговують на згадку тут. Він дуже простий у використанні. Перевір:
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()
Тепер у консолі:
% 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''
Ось метод, а не бібліотека, яка, здається, працює для мене.
Цілі тут повинні бути короткими, кожен аргумент розбирається одним рядком, аргументи складаються на читабельність, код простий і не залежить від будь-яких спеціальних модулів (лише os + sys), витончено попереджає про відсутні або невідомі аргументи , використовуйте простий цикл для / range () і працює через python 2.x та 3.x
Показані два тумблери (-d, -v) та два значення, керовані аргументами (-i xxx та -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))
Мета NextArg () - повернути наступний аргумент під час перевірки відсутніх даних, а "пропустити" пропускає цикл, коли NextArg () використовується, зберігаючи прапор розбору до одного вкладиша.
Я розширив підхід Ерко, щоб дозволити необхідні позиційні аргументи та необов'язкові аргументи. Вони повинні передувати аргументам -d, -v тощо.
Позиційні та необов'язкові аргументи можна отримати відповідно до PosArg (i) та OptArg (i, за замовчуванням). При виявленні необов'язкового аргументу початкове положення пошуку варіантів (наприклад, -i) переміщується на 1 вперед, щоб уникнути спричинення "несподіваного" летального результату.
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)