--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
は既に関数です(または2.xでprint
を関数として使用する場合) _from __future__ import print_function
_)を使用すると、さらに簡単になります。
_verboseprint = print if verbose else lambda *a, **k: None
_
この方法では、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 Docs および tutorials をご覧ください。
@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 __== '__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
いくつかのメモ:
3
のマジックナンバーは、ロギングの上限を設定しますが、簡単にするために妥協案として受け入れます。v_print
をプログラム全体で機能させたい場合は、グローバルでジャンクを実行する必要があります。面白くありませんが、誰かにもっと良い方法を見つけるように挑戦します。スクリプトで行うことは、実行時に「verbose」オプションが設定されているかどうかを確認し、ログレベルをデバッグに設定することです。設定されていない場合は、infoに設定します。この方法では、コード全体に「if verbose」チェックがありません。
私のプロジェクトの ロギングコード から virtualenv を盗みました。 virtualenv.py
のmain()
を見て 初期化方法 コードにlogger.notify()
、logger.info()
、logger.warn()
など。実際に出力を出すメソッドは、virtualenvが-v
、-vv
、-vvv
、または-q
のどれで呼び出されたかによって決まります。
冗長フラグをチェックするvprint
と呼ばれる関数がある場合は、よりクリーンになります。次に、オプションの冗長性が必要な場所で、独自のvprint
関数を呼び出すだけです。
グローバル変数は、おそらくsys.argv
からのargparse
で設定され、プログラムが冗長であるかどうかを表します。次に、冗長性がオンの場合、関数が実行される限り、標準入力がヌルデバイスに迂回されるようにデコレータを作成できます。
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 code ;に触発されています。実際、プログラムでモジュールとして使用するだけでしたが、理解できないエラーが発生したため、その一部を修正しました。
このソリューションの欠点は、logging
とは異なり、冗長性がバイナリであるため、プログラムの冗長性をさらに微調整できることです。また、allprint
呼び出しは迂回されますが、これは望ましくない可能性があります。
@ kindallの解決策 はmy Pythonバージョン3.5では動作しません。@ stylesは、理由が追加のオプションkeywords引数。したがって、Python 3のわずかに洗練されたバージョンは次のようになります。
if VERBOSE:
def verboseprint(*args, **kwargs):
print(*args, **kwargs)
else:
verboseprint = lambda *a, **k: None # do-nothing function
私が必要なのは、オブジェクト(obj)を出力する関数ですが、グローバル変数の詳細がtrueの場合にのみ、それ以外は何もしません。
グローバルパラメータ "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」もパラメータリストから設定できます。