2016-05-27 4 views
1

私はコマンドラインから引数を解析するPythonでarparseを使用していません。渡す周りの解析された引数には楽しい

は三つの方法がありますし、コールスタックが、私はthird_level()にいくつかのログを追加したいこの

def first_level(args): 
    second_level() 

def second_level(): 
    third_level() 

def third_level(): 
    ### here I want to add some logging if args.verbose is True 

のように見えます。

second_level()の署名を変更したくありません。

argオブジェクトをthird_lelvel()で利用できるようにするにはどうすればよいですか?

私はグローバル変数としてargを保存することができますが、私はこれを処理する一般的な方法は何ですか

....何年か前に開発者向けトレーニングでグローバル変数を使用しないように言われましたか?

+0

あなたの 'third_level(..) 'のログイン状態を解除してください。代わりに 'if args.verbose:logging.setLevel(logging.INFO)'を使用してください。 – SuperSaiyan

+0

私は 'args'オブジェクトを最初の関数に渡すだけです。他の人が値を必要とする場合は、必要なものを明確にするために関数のシグネチャの値として渡します。 'second_level(verbose = args.verbose)'などと呼んでください。 – Ben

答えて

2

私のコメントを回答に変換しています。私はあなたのthird_level(..)の状態を全く示唆しません。ロギングモジュールがそれを処理するメカニズムがあります。これらのメカニズムは、これら3つの機能の外部から制御することができます。

のような何か:

imports ... 
<constants> 
options = {verbose=0, etc} 
# alt options = argparse.Namespace(logging=False,....) 

def levelone(args, **kwargs): 
    .... 
def leveltwo(...): 

def levelthree(...): 
    <use constant> 
    <use options> 

def parser(): 
    p = argparse.ArgumentParser() 
    .... 
    args = p.parse_args() # this uses sys.argv 

if __name__=='__main__': 
     args = parser() 
     options.update(vars(args)) 
     levelone(args) 

モジュールの本体は関数定義を持っており、別のモジュールによってインポートすることができます。

def first_level(args): 
    second_level() 

def second_level(): 
    third_level() 

def third_level(): 
    logging.info("log line which will be printed if logging is at INFO level") 


def main(): 
    args = .... 
    #Set the logging level, conditionally 
    if args.verbose: 
     logging.basicConfig(filename='myapp.log', level=logging.INFO) 
    else: 
     logging.basicConfig(filename='myapp.log', level=logging.WARNING) 

    first_level(args) 
+0

はい、そうです。この場合、ロギングの使用が最適です。 args.fooへのアクセスが異なる目的のためのものであれば、別の解決策が必要です。しかし、これは別の質問です... – guettli

+0

私はおそらくクラス内の3つの関数をラップして(意味がある場合)、オブジェクト内の変数を設定します.3番目の関数は、 'self.variable' – SuperSaiyan

2

共通モジュール構造は、のようなものです。スクリプトとして使用された場合、parserはコマンドラインを読み込みます。そのグローバルoptionsは、すべての種類のstateのようなパラメータで利用できます。意味では、ユーザーまたはインポートモジュールが調整できる定数です。 configファイルからインポートされた値は、同じ役割を持つことができます。

もう1つのよくあるパターンは、クラスの関数メソッドを作成し、オブジェクト属性としてargsを渡すことです。彼らは使い古さ取得し、機能が提供するモジュール性を損なうので

class Foo(): 
    def __init__(self, logging=False): 
     self.logging = logging 
    def levelone(): 
    def leveltwo(): 
     <use self.logging> 
foo(args.logging).levelone() 

globalsが推奨されますが、それはより多くのです。しかし、Pythonには、関数とクラス以外のものを含むことができるレベル名前空間moduleも用意されています。また、モジュール内で定義されている関数はすべて、その名前空間にアクセスすることができます。

var1 = 'module level variable' 
var2 = 'another' 
def foo(var3): 
    x = var1 # read/use var1 
    var2 = 1 # shadow the module level definition 
    etc 

================

私はこれをお勧めしたりすべきではないわからないんだけど、あなたはthird_levelsys.argvを解析できます。

def third_level(): 
    import argparse 
    p = argparse.ArgumentParser() 
    p.add_argument('-v','--verbose',action='count') 
    args = p.parse_known_args() 
    verbose = args.verbose 
    <logging> 

​​輸入syssys.argvを使用しています。これは、あなたのスクリプトレベル、あなたのmainまたはいくつかのネストされた関数で使用されているかどうかに関係なく行うことができます。 loggingは同じことをしています。独自のインポートされたモジュールを使用して、値を関数に秘密裏に渡すことができます。明らかに、それは虐待される可能性があります。クラス属性を持つclassもこの方法で使用できます。

関連する問題