Я знаю --verbose
или -v
из нескольких инструментов, и я хотел бы реализовать это в некоторых из моих собственных скриптов и инструментов.
Думал разместить:
if verbose:
print ...
через мой исходный код, так что, если пользователь передает -v
параметр, переменная verbose
будет установлена в значение, True
и текст будет напечатан.
Это правильный подход или есть более распространенный способ?
Дополнение: я не прошу способа реализовать синтаксический анализ аргументов. Я знаю, как это делается. Меня особенно интересует только подробный вариант.
Ответы:
Мое предложение - использовать функцию. Но вместо того, чтобы вставлять
if
в функцию, что может возникнуть соблазн сделать, сделайте это так:if verbose: def verboseprint(*args): # Print each argument separately so caller doesn't need to # stuff everything to be printed into a single string for arg in args: print arg, print else: verboseprint = lambda *a: None # do-nothing function
(Да, вы можете определить функцию в
if
операторе, и она будет определена, только если условие истинно!)Если вы используете Python 3, где
print
уже есть функция (или если вы хотите использоватьprint
как функцию в 2.x, используяfrom __future__ import print_function
), это еще проще:verboseprint = print if verbose else lambda *a, **k: None
Таким образом, функция определяется как бездействующая, если подробный режим выключен (с использованием лямбда), вместо постоянного тестирования
verbose
флага.Если бы пользователь мог изменить режим детализации во время выполнения вашей программы, это был бы неправильный подход (вам понадобится
if
функция в функции), но, поскольку вы устанавливаете его с помощью флага командной строки, вам нужно только принять решение один раз.Затем вы можете использовать, например,
verboseprint("look at all my verbosity!", object(), 3)
всякий раз, когда хотите распечатать «подробное» сообщение.источник
print
функцию: принять много аргументов. Его можно реализовать какprint(*args)
в 3.x, так иfor arg in args: print arg,
в 2.x. Основное преимущество заключается в том, что он позволяет смешивать строки и вещи других типов в одном сообщении без явныхstr
вызовов / форматирования и конкатенации.print arg,
строки?def verboseprint(*args, **kwargs): print(*args, **kwargs)
Используйте
logging
модуль:import logging as log … args = p.parse_args() if args.verbose: log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG) log.info("Verbose output.") else: log.basicConfig(format="%(levelname)s: %(message)s") log.info("This should be verbose.") log.warning("This is a warning.") log.error("This is an error.")
Все они автоматически попадают в
stderr
:Для получения дополнительной информации см. Документы Python и руководства .
источник
Создание и упрощение ответа @ kindall, вот что я обычно использую:
v_print = None def main() parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbosity', action="count", help="increase output verbosity (e.g., -vv is more than -v)") args = parser.parse_args() if args.verbosity: def _v_print(*verb_args): if verb_args[0] > (3 - args.verbosity): print verb_args[1] else: _v_print = lambda *a: None # do-nothing function global v_print v_print = _v_print if __name__ == '__main__': main()
Затем это обеспечивает следующее использование в вашем скрипте:
v_print(1, "INFO message") v_print(2, "WARN message") v_print(3, "ERROR message")
А ваш скрипт можно назвать так:
Пара заметок:
3
которое устанавливает верхнюю границу для вашего журнала, но я принимаю это как компромисс для простоты.v_print
работать над всей своей программой, вам придется делать мусор с помощью global. Это не весело, но я призываю кого-нибудь найти лучший способ.источник
-v
используется. В вашем текущем решении все выгружается в stdout вместо stderr. И: обычно вы хотите передавать пользователю каждую ошибку, не так ли?В своих сценариях я проверяю во время выполнения, установлен ли параметр «подробный», а затем устанавливаю уровень ведения журнала для отладки. Если он не установлен, я устанавливаю его на info. Таким образом, у вас не будет проверок «если подробный» по всему вашему коду.
источник
Было бы проще, если бы у вас была функция, скажем, вызываемая
vprint
, которая проверяет за вас подробный флаг. Затем вы просто вызываете свою собственнуюvprint
функцию в любом месте, где хотите, по желанию.источник
Я украл код регистрации из virtualenv для своего проекта. Посмотрите на
main()
о ,virtualenv.py
чтобы увидеть , как она инициализируется. Код посыпаютlogger.notify()
,logger.info()
,logger.warn()
и тому подобное. Какие методы фактически Испустите выход определяется , был ли virtualenv вызывается с-v
,-vv
,-vvv
или-q
.источник
Решение @ kindall не работает с моей версией Python 3.5. @styles правильно заявляет в своем комментарии, что причиной является дополнительный необязательный аргумент ключевых слов . Следовательно, моя слегка доработанная версия для Python 3 выглядит так:
if VERBOSE: def verboseprint(*args, **kwargs): print(*args, **kwargs) else: verboseprint = lambda *a, **k: None # do-nothing function
источник
Может быть глобальная переменная, которая, скорее всего, устанавливается с помощью
argparse
fromsys.argv
, которая указывает, должна ли программа быть подробной или нет. Затем можно написать декоратор таким образом, чтобы при включенной многословности стандартный ввод был перенаправлен на нулевое устройство, пока функция должна была выполняться:import os from contextlib import redirect_stdout verbose = False def louder(f): def loud_f(*args, **kwargs): if not verbose: with open(os.devnull, 'w') as void: with redirect_stdout(void): return f(*args, **kwargs) return f(*args, **kwargs) return loud_f @louder def foo(s): print(s*3) foo("bar")
Этот ответ вдохновлен этим кодом ; на самом деле, я собирался просто использовать его как модуль в своей программе, но у меня были ошибки, которые я не мог понять, поэтому я адаптировал его часть.
Обратной стороной этого решения является то, что подробность является двоичной, в отличие от with
logging
, что позволяет более точно настраивать степень подробности программы. Кроме того, всеprint
вызовы переадресовываются, что может быть нежелательным.источник
Что мне нужно, так это функция, которая печатает объект (obj), но только если глобальная переменная verbose истинна, иначе она ничего не делает.
Я хочу иметь возможность изменить глобальный параметр "подробный" в любое время. Для меня простота и удобочитаемость имеют первостепенное значение. Итак, я бы продолжил, как указывают следующие строки:
ak@HP2000:~$ python3 Python 3.4.3 (default, Oct 14 2015, 20:28:29) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>> verbose = True >>> def vprint(obj): ... if verbose: ... print(obj) ... return ... >>> vprint('Norm and I') Norm and I >>> verbose = False >>> vprint('I and Norm') >>>
Глобальную переменную "verbose" также можно установить из списка параметров.
источник