Programing

--verbose 또는 -v 옵션을 스크립트에 구현하는 방법은 무엇입니까?

lottogame 2020. 10. 14. 07:20
반응형

--verbose 또는 -v 옵션을 스크립트에 구현하는 방법은 무엇입니까?


나는 알고 --verbose또는 -v여러 툴을 나는 내 자신의 스크립트와 도구의 일부에이를 구현하고 싶습니다.

나는 배치를 생각했다 :

if verbose:
    print ...

내 소스 코드를 통해 사용자가 -v옵션을 전달 하면 변수 verbose가로 설정되고 True텍스트가 인쇄됩니다.

이것이 올바른 접근 방식입니까 아니면 더 일반적인 방법이 있습니까?

추가 : 인수 구문 분석을 구현하는 방법을 요구하지 않습니다. 나는 그것이 어떻게 행해지는지 압니다. 나는 verbose 옵션에만 특별히 관심이 있습니다.


내 제안은 기능을 사용하는 것입니다. 하지만 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명령문 에서 함수를 정의 할 수 있으며 조건이 참인 경우에만 정의됩니다!)

print이미 함수가 있는 Python 3 을 사용하는 경우 ( print또는를 사용하여 2.x에서 함수 로 사용하려는 경우 from __future__ import print_function) 더 간단합니다.

verboseprint = print if verbose else lambda *a, **k: None

이렇게하면 verbose플래그 를 지속적으로 테스트하는 대신 verbose 모드가 꺼져있는 경우 (람다 사용) 함수가 아무것도하지 않는 것으로 정의됩니다 .

사용자가 프로그램을 실행 하는 동안 상세 모드를 변경할 수 있다면 이것은 잘못된 접근 방식입니다 ( if함수에서 필요 ).하지만 명령 줄 플래그로 설정하기 때문에 한 번 결정하십시오.

그런 다음 verboseprint("look at all my verbosity!", object(), 3)"verbose"메시지를 인쇄 할 때마다 예를 사용 합니다.


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 myprogram.py
WARNING: This is a warning.
ERROR: This is an error.

% python myprogram.py -v
INFO: Verbose output.
INFO: This should be verbose.
WARNING: This is a warning.
ERROR: This is an error.

자세한 내용은 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")

그리고 스크립트는 다음과 같이 호출 할 수 있습니다.

% python verbose-tester.py -v
ERROR message

% python verbose=tester.py -vv
WARN message
ERROR message

% python verbose-tester.py -vvv
INFO message
WARN message
ERROR message

몇 가지 참고 사항 :

  1. 첫 번째 인수는 오류 수준이고 두 번째 인수는 메시지입니다. 3로깅의 상한을 설정 하는 매직 넘버가 있지만 단순성을위한 타협으로 받아들입니다.
  2. v_print프로그램 전체에서 일하고 싶다면 글로벌과 함께 쓰레기를 처리해야합니다. 재미는 없지만 더 나은 방법을 찾기 위해 누군가에게 도전합니다.

What I do in my scripts is check at runtime if the 'verbose' option is set, and then set my logging level to debug. If it's not set, I set it to info. This way you don't have 'if verbose' checks all over your code.


It might be cleaner if you have a function, say called vprint, that checks the verbose flag for you. Then you just call your own vprint function any place you want optional verbosity.


I stole the logging code from virtualenv for a project of mine. Look in main() of virtualenv.py to see how it's initialized. The code is sprinkled with logger.notify(), logger.info(), logger.warn(), and the like. Which methods actually emit output is determined by whether virtualenv was invoked with -v, -vv, -vvv, or -q.


@kindall's solution does not work with my Python version 3.5. @styles correctly states in his comment that the reason is the additional optional keywords argument. Hence my slightly refined version for Python 3 looks like this:

if VERBOSE:
    def verboseprint(*args, **kwargs):
        print(*args, **kwargs)
else:
    verboseprint = lambda *a, **k: None # do-nothing function

There could be a global variable, likely set with argparse from sys.argv, that stands for whether the program should be verbose or not. Then a decorator could be written such that if verbosity was on, then the standard input would be diverted into the null device as long as the function were to run:

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")

This answer is inspired by this code; actually, I was going to just use it as a module in my program, but I got errors I couldn't understand, so I adapted a portion of it.

The downside of this solution is that verbosity is binary, unlike with logging, which allows for finer-tuning of how verbose the program can be. Also, all print calls are diverted, which might be unwanted for.


What I need is a function which prints an object (obj), but only if global variable verbose is true, else it does nothing.

I want to be able to change the global parameter "verbose" at any time. Simplicity and readability to me are of paramount importance. So I would proceed as the following lines indicate:

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')
>>> 

Global variable "verbose" can be set from the parameter list, too.

참고URL : https://stackoverflow.com/questions/5980042/how-to-implement-the-verbose-or-v-option-into-a-script

반응형