如何让'import x'返回types.ModuleType的子类?

joe*_*ker 7 python

Python的import语句可以返回types.ModuleType使用导入钩子的子类吗?我想覆盖__getattribute__以在某个模块引用名称不在其中的代码之外显示运行时警告__all__.

我知道如何sys.modules['foo']在导入后进行更换.我想要的是模式匹配的仪器模块,因为它们都是进口,因此进口的代码有机会触发警告.

Python对公开和私密化的想法不以为然.这个想法不是要阻止你的模块用户打字from somemodule import sys; 相反,它是一个文档工具.这种仪器应该通过包含正确的文档来更容易地记录模块的API __all__.它应该可以帮助您避免意外引用sys,somemodule.sys而不是简单地引用import sys.

kin*_*all 5

因为在你编辑它之前我错过了你的问题的重点,我想我会再次打击(留下我原来的答案给后人).

这是一个也不需要导入钩子的替代方案.它可以在逐个模块的基础上轻松使用:包含此代码的模块将具有特殊__getattribute__()行为,而其他模块将像往常一样运行.

class StrictModule(types.ModuleType):

    def __getattribute__(self, key):
        if key is "__dict__":  # fake __dict__ with only visible attributes
            return dict((k, v) for k, v in globals().iteritems()
                        if k.startswith("__") or k in __all__)
        if (key.startswith("__") or key in __all__) and key in globals():
            return globals()[key]
        else:
            raise AttributeError("'module' object has no attribute '%s'"  % key)

    def __setattr__(self, key, value):
        globals()[key] = value

sys.modules[__name__] = StrictModule(__name__)
Run Code Online (Sandbox Code Playgroud)

请记住,通过简单地调用常规module类型__getattribute__()(或object类型的类型),这种"限制"很容易解决.我的印象是你试图为你的模块提供某种"私人成员"限制.这几乎没有任何意义.

  • 不,但是`help()`即使没有`__all__`也不显示模块,所以没有必要. (2认同)

kin*_*all 3

您甚至不需要导入钩子。只需将对 Python 模块注册表中的对象的引用放在sys.modules所需名称下,importPython 会话中的任何未来语句(甚至在其他模块中)都将导入对该实体的引用。

import types, sys

class MyModuleType(types.ModuleType):
    pass

sys.modules["foo"] = MyModuleType("foo")

import foo

print type(foo)   # MyModuleType
Run Code Online (Sandbox Code Playgroud)

Python 甚至不关心其中的对象sys.modules实际上是模块还是完全其他类型的对象。你可以在那里扔一个int,但不会给出任何f***。

sys.modules["answer"] = 42
import answer
Run Code Online (Sandbox Code Playgroud)