2013-10-22 18 views
5

インポートしたモジュールからインポートするモジュールにコードを適用できますか? 例えば、私はモジュールのデバッグ例えば、デバッグのためのいくつかのデコレータを定義している:Pythonのイントロスペクション

def debug_func(f): 
    def wrapper(*func_args, **func_kwargs): 
     print(f(*func_args, **func_kwargs)) 
    return wrapper 

何でしょう:私はちょうど

import Debug 

と現在のモジュールからのすべての機能をできればだが有用であろうデコレータで包まれます。 可能ですか? Debug.py内

+1

インポート後に 'Debug'で関数を呼び出す必要があります。 'Debug'はおそらくインポートモジュール自身がインポートされている間はインポートモジュールに反映されません。IMHO、あなたは 'debug import from debug_func'を実行し、それを必要とする関数で' @ debug_func'デコレータを使う方が良いでしょう。ファイル内の '@ debug_func'のすべてのインスタンスのコメントやコメント解除ができる正規表現を書くのは難しいことではありません。 –

+1

私は 'decorate_all'関数を書くことができます。関数はパラメータとして関数を受け取り、' gobals() 'の' callable'エントリをすべて見て、それらを飾るか、それと似ています。インポート後にこれを呼び出します。 –

答えて

3

:あなたはデバッグに希望されているモジュールの

import functools 
from types import FunctionType 

def wrap_functions(module_dict): 
    for k, f in module_dict.items(): 
     if not isinstance(f, FunctionType): 
      continue 
     def get_wrapper(f): 
      def wrapper(*func_args, **func_kwargs): 
       print(f(*func_args, **func_kwargs)) 
      return functools.wraps(f)(wrapper) 
     module_dict[k] = get_wrapper(f) 

:提案を提供し、すべてのコメンターへ

import Debug 
Debug.wrap_functions(globals()) 

おかげで(1)。

+0

あなたはそれを後ろに持っています。デバッグの関数ではなく、インポートするモジュールの関数をラップするために 'import Debug'を望みます。 –

+1

関数でデコレータをコピーするのではなく、デコレータを別のパラメータとして渡すのはなぜですか?また、 'Debug.wrap_functions(globals())'を使うのが良いでしょう。さもなければ 'wrap_function'がそれ自身を飾ります。それ以外は+1 –

+1

私はあなたの元の答えを読んでから、いくつかの点検をするために離れて行き、私が書いていた計画を見つけるために戻って来ました:)。 –

0

私のようなコールと標準ツール(pdbunittest、...)として、それを行うのニシキヘビの方法は、あなたのデバッグデバッグモジュールを呼び出す持っているだろうと思う:あなたと

$ python -m Debug mymodule.py 

あなたが好きなデコレータでモジュールをインポート/実行することをデバッグします。あなたがDebugモジュールをそれをインポートするモジュールに依存させようとしているので、他の方法(Debugをインポートする)は、モジュールが評価される順序を乱します。別にジム・ギャリソンが示唆したように、いくつかのDebug.mark_as_debugに(globals()、関数の一覧...を経由して)明示的に関数を渡すから

は、私はそれはあなたがあなたのDebug呼び出すことができますようにあなたのコードを整理するために多くの意味をなすと思うあなた他の方法ではなくモジュールを使用します。

+0

ありがとう、しかし、私は主な問題としてデバッグを書いた - どのようなインポートされたモジュールからそれをインポートするモジュールにコードを適用する最善の方法です。 – Dmitriy

+0

私はこの質問への答えは、あなたができないと思います。私はそれよりはるかに優れていると説明していますが、モジュールの原則はそれに反しています(インポートモジュールから呼び出されるフックをJim Garrisonが示したように追加することもできます)。私はモジュールにその呼び出し元を知らせ、コールバックなしでそれを修正する方法はないと思う。 – val

+0

技術的には、あなたはインポートフックでそれを行うことができると思うが、それは非常に汚れているようだ。 – kindall

3

Debugはどのモジュールをインポートするのですか?答え:できません。 Debugは、複数のモジュールにインポートされた場合、どのように2回以上実行することができますか?答え:そうではありません。モジュールは一度だけ実行されてからキャッシュされます。だからあなたがしたいことは、あなたが望むだけ単純にすることはできません。

ただし、インポート後にdebugモジュール内の関数を呼び出すことで可能です。呼び出し元のモジュールから__name__を渡してその名前を渡すことができます。その後、モジュール自身への参照を取得し、その中で定義されているトップレベルの変数を取得することができます。これらは装飾されるかもしれません。

呼び出しモジュールで今すぐ
# debug.py 
import types, sys, functools 

# decorator to be applied to all top-level functions in a module 
def debug(fn): 
    @functools.wraps(fn) 
    def wrapper(*args, **kwargs): 
     print "calling", fn.__name__, "with args", *args, **kwargs 
     result = fn(*args, **kwargs) 
     print "returning from", fn.__name__, "with return value", result 
     return result 

# decorate all top-level functions in named module with a given decorator 
# (by default it is the above decorator but it could be a different one) 
# This makes these functions behave as though they had been written with 
# @debug above them. 
def set_debug(modname, debug=debug): 
    module = sys.modules[modname] 
    for name in dir(module): 
     if not name.startswith("_"): 
      thing = getattr(module, name) 
      if isinstance(thing, types.FunctionType): 
       setattr(module, name, debug(thing)) 

:(むしろモジュール名より)、明示的に名前空間を渡すの

# main.py 
import debug 

def main(): 
    print "in main module" 

debug.set_debug(__name__) # install debugging decorator 

main() 

ジム・ギャリソンのアプローチも良いですし、実際に物事ビットを簡素化します。モジュール以外のものを装飾するために使用することができます。私は鉱山を壊してしまったので、あなたが望むなら別のデコレータを渡すことができます。

関連する問題