如何只从模块加载一个类?

时间:2014-02-18 21:51:15

标签: python python-2.x python-import

我有代码:

mod_file = 'mymod.py'
mod_path = os.path.join('.', mod_file)
mod_py = 'mymod'
mod = imp.load_source(mod_py, mod_path)
if hasattr(mod, 'MyClass'):
    instance = py_mod.MyClass()

mymod.py:

class MyClass():

    def __init__(self):
        print 'Hello'
    [...]

print 'something'
a = MyClass()

但是“imp.load_source”执行此文件中的所有指令。我只想获得MyClass类 - 其他的东西都跳过了。怎么做?

编辑:

我不能干涉“mymod.py”文件,我不知道该文件将如何命名,这是一个例子。

我知道在文件中将是'MyClass'类。其他事情是不可取的。

6 个答案:

答案 0 :(得分:3)

您可以像mymod.py那样将结束行包装起来:

if __name__ == "__main__":
    print 'something'
    a = MyClass()

结果将是这些行仅在mymod.py作为脚本执行时执行,而不是作为模块导入。请参阅Python文档中的executing modules as scripts

但请注意,如果您在mymod.py中定义了其他类,则仍会由imp.load_source导入。

修改:由于您无法修改mymod.py,因此解决方案变得更加复杂。您可以使用ast模块来解析代码:

import ast
with open("mymod.py", "r") as fd:
    module_ast = ast.parse("".join(fd.readlines()))

然后,您将遍历ast(module_ast)并隔离MyClass树节点。此链接提供example内联修改python代码,这显示如何analyse code。您可以使用这些链接中的技术组合来隔离与ast相关的MyClass节点,并删除其余节点。但这最终会对mymod.py实际包含的内容做出一些假设。

答案 1 :(得分:3)

这在Python中是不可能的。您应该设计代码,使其在导入时没有副作用。

另外,请注意,模块只执行一次,无论您使用import module多少次,所以依赖非常糟糕的主意关于模块导入的副作用。

尽管如此,如果您需要的是让您的模块在导入时的行为与运行时的行为不同,那么您可以通过使用以下方式实现该目标:

# module.py
# Code that will always run
...

if __name__ == "__main__":
    # Code that will only run if you do python module.py
    # Usually print statements, argument parsing... 
    ...

在你的情况下,你会这样做:

    class MyClass():

    def __init__(self):
        print 'Hello'
    [...]

if __name__ == "__main__":
    print 'something'
    a = MyClass()

使用它的常用方法是:

def main():
     # do stuff

if __name__ == "__main__":
    main()

答案 2 :(得分:1)

class MyClass():

    def __init__(self):
        print 'Hello'
    [...]

if __name__ == '__main__':
    print 'something'
    a = MyClass()

if __name__块中的所有语句只有在直接执行该模块时才会执行,而不是在导入模块时执行。

答案 3 :(得分:0)

我相信这里最pythonic的解决方案是从你的其他Python文件中导入类。为此,请将imp.load_source()替换为:

 from mymod import MyClass

答案 4 :(得分:0)

第1步 - 使用以下代码创建文件main.py

from MyFolder import MyClass
instance = MyClass()
# Do whatever you wanna do with the MyClass instance...

第2步 - 在文件MyFolder旁边创建文件夹main.py

第3步 - 将文件mymod.py重命名为__init__.py,并将其放在文件夹MyFolder内。

答案 5 :(得分:0)

  1. 不要编写自己的插件系统。已经有太多了。
  2. 虽然理论上可以检查模块的AST只能提取你需要的位,但这实际上会导致各种奇怪的角落情况,这是一个坏主意。不要这样做。要求插件的编写方式可以在没有副作用的情况下导入。