是否可以将导入模块中的代码应用于导入它的模块?例如,我有模块 Debug ,其中定义了一些用于调试的装饰器,例如:
def debug_func(f):
def wrapper(*func_args, **func_kwargs):
print(f(*func_args, **func_kwargs))
return wrapper
想法是什么:如果我能做到这将是有用的
import Debug
当前模块中的所有功能都将用装饰器包装。是否可以?
是否可以将导入模块中的代码应用于导入它的模块?例如,我有模块 Debug ,其中定义了一些用于调试的装饰器,例如:
def debug_func(f):
def wrapper(*func_args, **func_kwargs):
print(f(*func_args, **func_kwargs))
return wrapper
想法是什么:如果我能做到这将是有用的
import Debug
当前模块中的所有功能都将用装饰器包装。是否可以?
在 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) 所有提供建议的评论者。
如何Debug知道它是从哪个模块导入的?答:不能。如果它被导入到多个模块中,怎么会Debug知道运行不止一次?答:不会;模块只运行一次然后缓存。所以你想做的事情不能像你想做的那样简单。
但是,您可以通过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 显式传递命名空间(而不是模块名称)的方法也很好,实际上简化了一些事情;你可以用它来装饰模块以外的东西。我已经分解了我的,因此您可以根据需要传入不同的装饰器。
我认为这样做的pythonic方法是让您的Debug调用调试模块,作为标准工具(pdb,,unittest...),调用如下:
$ python -m Debug mymodule.py
随着您的调试使用您喜欢的任何装饰器导入/执行模块。以另一种方式(导入Debug)会混淆模块的评估顺序,因为您试图让您的Debug模块依赖于导入它的模块,这充其量是棘手的。
除了像 Jim Garrison 建议的那样将你的函数显式传递(通过globals()函数列表......)之外Debug.mark_as_debug,我认为组织你的代码更有意义,这样你就可以Debug调用你的模块而不是相反.