#python #argparse
#python #argparse
Вопрос:
Давайте рассмотрим приведенный ниже пример. Анализатор содержит два аргумента — inputfile и verbosity. Функция Set_verbosity_level() используется для управления значением глобальной переменной уровня модуля (в моей реальной жизни переменной уровня пакета) равным 0-4. Функция CheckFile() выполняет тесты внутри входного файла (в реальной жизни в зависимости от типа). Я хотел бы печатать сообщения в CheckFile () в зависимости от детализации. Проблема в том, что argparse вызывает CheckFile() перед Set_verbosity_level(), поэтому уровень детализации в CheckFile всегда равен 0 / по умолчанию…
Итак, мой вопрос заключается в том, существует ли какое-либо решение, чтобы заставить argparse оценивать некоторые аргументы перед другими…
import argparse
VERBOSITY = 0
def Set_verbosity_level():
"""Set the verbosity level.
"""
def type_func(value):
a_value = int(value)
globals()['VERBOSITY'] = value
print("Verbosity inside Set_verbosity_level(): " str(globals()['VERBOSITY']))
return value
return type_func
class CheckFile(argparse.FileType):
"""
Check whatever in the file
"""
def __init__(self, mode='r', **kwargs):
super(CheckFile, self).__init__(mode, **kwargs)
def __call__(self, string):
# Do whatever processing/checking/transformation
# e.g print some message according to verbosity
print("Verbosity inside CheckFile(): " str(globals()['VERBOSITY']))
return super(CheckFile, self).__call__(string)
def make_parser():
"""The main argument parser."""
parser = argparse.ArgumentParser(add_help=True)
parser.add_argument("-V",
"--verbosity",
default=0,
type=Set_verbosity_level(),
help="Increase output verbosity.",
required=False)
parser.add_argument('-i', '--inputfile',
help="Input file",
type=CheckFile(mode='r'),
required=True)
return parser
if __name__ == '__main__':
myparser = make_parser()
args = myparser.parse_args()
print("Verbosity in Main: " str(VERBOSITY))
Вызов этого скрипта дает:
$python test.py -i test.bed -V 2
Verbosity inside CheckFile(): 0
Verbosity inside Set_verbosity_level(): 2
Verbosity in Main: 2
Комментарии:
1. Он анализирует входные данные в порядке, который предоставляет ваш пользователь, и мы не можем легко изменить эту процедуру синтаксического анализа. Я думаю, что имеет больше смысла
CheckFile
после синтаксического анализа, когда вы знаете детализацию независимо от порядка ввода. В PY3 удобнее открывать файлы вwith
контексте, чего вы не можете сделать сargparse.FileType
. Установка глобального значенияVERBOSITY
изнутриtype
функции является новой и, на мой взгляд, не в хорошем стиле Python.
Ответ №1:
argparse
обрабатывает аргументы командной строки в том порядке, в котором они перечислены, поэтому, если вы просто измените порядок заданных параметров, он будет выводиться с требуемой подробностью:
python test.py -V 2 -i test.bed
Это выводит:
Verbosity inside Set_verbosity_level(): 2
Verbosity inside CheckFile(): 2
Иначе невозможно указать argparse
обрабатывать аргументы командной строки в порядке, отличном от того, как они перечислены.
Комментарии:
1. Я предполагаю, что это должен быть выбранный ответ на вопрос «Есть ли способ контролировать порядок вычисления аргументов в Python argparse». Я выберу ответ Ричарда, который выходит за рамки и предлагает решение моего конкретного ограничения. Лучшие
Ответ №2:
Я не знаю, можете ли вы принудительно прочитать переменную argparse первой, но вы можете использовать pythons, встроенные в анализатор командной строки в вашей основной функции:
import sys
# Your classes here #
if __name__ == '__main__':
verbosity = 0
for i, sysarg in enumerate(sys.argv):
if str(sysarg).strip().lower().replace('-','') in ['v', 'verbose']:
try:
verbosity = sys.argv[i 1]
except IndexError:
print("No verbosity level specified")
# more code
Это не очень элегантно, и это не argparse, но это один из способов гарантировать, что вы получите детализацию в первую очередь.
Вы также могли бы обновить свой CheckFile
класс, включив в него функцию проверки подробностей:
class CheckFile(argparse.FileType):
"""
Check whatever in the file
"""
def __init__(self, mode='r', **kwargs):
super(CheckFile, self).__init__(mode, **kwargs)
def _check_verbosity(self):
verbosity = 0
for i, sysarg in enumerate(sys.argv):
if str(sysarg).strip().lower().replace('-','') in ['v', 'verbose']:
try:
verbosity = sys.argv[i 1]
except IndexError:
print("No verbosity level specified")
return verbosity
def __call__(self, string):
# Do whatever processing/checking/transformation
# e.g print some message according to verbosity
print("Verbosity inside CheckFile(): {}".format(self._check_verbosity()))
return super(CheckFile, self).__call__(string)
Опять же, я знаю, что на самом деле это не ответ на ваш вопрос argparse, но это решение вашей проблемы
Комментарии:
1. Я думаю, что второе решение должно сработать. Большое спасибо, Ричард, за помощь.