Python,将代码注入模块全局

时间:2018-03-03 12:32:49

标签: python python-3.x dictionary module

我试图绕过从模块导入,所以在__init__.py我可以注入这样的代码:

globals().update(
    {
         "foo": lambda: print("Hello stackoverflow!")
    }
)

所以,如果我import mymodule,我可以致电mymodule.foo。这是一个简单的概念,对此无用,因为您实际上只能定义foo。 所以,我的想法是修改globals模块字典,所以如果它找不到函数foo它会去任何地方,我可以注入代码,为此我试过:< / p>

from importer import load #a load function to search for the code
from functools import wraps

def global_get_wrapper(f):
    @wraps(f)
    def wrapper(*args):
        module_name, default = args
        res = f(*args)
        if res is None:
            return load(module_name)
        return res
    return wrapper

globals().get = global_get_wrapper(globals().get) # trying to substitute get method

但它给了我一个错误:

AttributeError: 'dict' object attribute 'get' is read-only

我的另一个想法是将可用的函数,类等名称预加载到模块字典中,然后懒洋洋地加载它们。

我没有想法来实现这一目标,我也不知道这是否可行。 我应该去写我自己的python导入器吗?还是有其他我无法思考的可能性? 提前谢谢。

3 个答案:

答案 0 :(得分:7)

不是黑客攻击globals(),最好为您的模块定义__getattr__,如下所示:

module_name.py

foo = 'foo'

def bar():
    return 'bar'

my_module.py

import sys

import module_name

class MyModule(object):
    def foobar(self):
        return 'foobar'

    def __getattr__(self, item):
        return getattr(module_name, item)

sys.modules[__name__] = MyModule()

然后:

>>> import my_module
>>> my_module.foo
'foo'
>>> my_module.bar()
'bar'
>>> my_module.foobar()
'foobar'

答案 1 :(得分:3)

针对Python 3.7的

PEP 562为模块引入了__getattr__。在理论基础上,它还描述了以前的Python版本的变通方法。

  

有时可以方便地定制或以其他方式控制对模块属性的访问。一个典型的例子是管理弃用警告。典型的解决方法是将模块对象的__class__分配给types.ModuleType的自定义子类,或者使用自定义包装器实例替换sys.modules项。通过识别直接在模块中定义的__getattr__来简化此过程将会很方便,该模块将像普通的__getattr__方法一样,除了它将在模块实例上定义。

所以您的mymodule可能如下:

foo = 'bar'

def __getattr__(name):
    print('load you custom module and return it')

以下是它的表现:

>>> import mymodule
>>> mymodule.foo
'bar'
>>> mymodule.baz
load you custom module and return it

答案 2 :(得分:0)

我不太明白。这对你有用吗?

try:
    mymodule.foo()
except:
    print("whatever you wanted to do")