5

インポートされたモジュールからそれをインポートするモジュールにコードを適用することは可能ですか? たとえば、次のようなデバッグ用のデコレータを定義したモジュール Debug があります。

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

アイデアは何ですか:私ができるならそれは役に立ちます

import Debug 

現在のモジュールのすべての関数はデコレータでラップされます。出来ますか?

4

3 に答える 3

3

Debug.py 内:

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) します。

于 2013-10-22T14:45:22.833 に答える
3

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

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

(モジュール名ではなく) 名前空間を明示的に渡すという Jim Garrison のアプローチも優れており、実際には少し単純化されています。モジュール以外のものを装飾するために使用できます。必要に応じて別のデコレータを渡すことができるように、私は私のものを分割しました。

于 2013-10-22T15:02:52.233 に答える
0

それを行うpythonicの方法は、次のような呼び出しを使用して、デバッグされたモジュールを標準ツール(、、pdb... unittest)としてデバッグに呼び出すことだと思います。

$ python -m Debug mymodule.py

好きなデコレータでモジュールをデバッグインポート/実行します。他の方法 (インポート) を行うと、モジュールが評価される順序が乱れます。モジュールをインポートするモジュールに依存さDebugせようとしているからです。Debug

globals()ジム・ギャリソンが提案したように、関数を明示的に(関数のリストを介して...)渡すこととは別に、モジュールを呼び出すDebug.mark_as_debugことができるようにコードを整理する方が理にかなっていると思います。Debug.

于 2013-10-22T15:02:22.577 に答える