Python - 动态导入后未定义的类名

时间:2012-07-05 13:00:32

标签: python class dynamic import

我现在使用Python已经有好几个星期了,我遇到了动态导入的问题。 我有一个文件Test.py,其中定义了一个类。我想在从另一个文件动态导入Test.py之后使用这个类。

我的最终目标更复杂,但我简化了它,但我仍然遇到同样的问题。

文件:Test.py

class Test :
    def __init__ ( self ) :
        print ( "instance" )

文件:Main.py

def allImports ( ) :
    __import__ ( "Test" )

我得到了什么:

>>> import Main
>>> Main.allImports()
>>> myInstance = Test ()
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
NameError: name 'Test' is not defined

我无法在fromlist中指定Test.py中哪个元素必须导入,因为我不应该知道它们。

我该怎么办?

4 个答案:

答案 0 :(得分:2)

更接近你意图的解决方案:

import importlib
def allImports(globals):
    mod = importlib.import_module('Test', globals['__name__'])

    try:
        keys = mod.__all__
    except AttributeError:
        keys = dir(mod)

    for key in keys:
        if not key.startswith('_'):
            globals[key] = getattr(mod, key)

# …

allImports(globals())
Test # should work, you can also look into dir(Test) to find the class.

如果你的模块没有__all__上面的代码/会/你的命名空间是一些激烈的东西。要么确保定义__all__,要么修改allImports()以仅导入所需的内容。 (例如,只有类,或者只在模块中定义的类。这部分实际上取决于您的用例。)

答案 1 :(得分:1)

此代码使__import__ ( "Test" )成为局部变量,因此您无法在函数外部访问它。

   def allImports ( ) :
        __import__ ( "Test" )

<强>尝试:

def allImports ( ) :
   test= __import__ ( "Test" )
   return test   #return the module

>>> import Main
>>> x=Main.allImports()  #store the returned module in x
>>> myInstance = x.Test ()
instance
>>>myInstance
<Test.Test instance at 0x011D7F80>

答案 2 :(得分:1)

使用__import__()加载模块时,您必须在sys.modules中查找:

>>> import sys
>>> import Main
>>> Main.allImports()
>>> myInstance = sys.modules['Test'].Test()
instance
>>>

documentationhereherehere中的详细信息。

答案 3 :(得分:1)

__import__不会神奇地修改全局命名空间和本地命名空间。

模块和类是Python中的第一类公民,即,您可以将它们用作Python中的任何其他对象(绑定到名称,作为参数传递给函数,作为函数返回值)。

def allImports():
    return __import__("Test")

Test_module = allImports()
Test = Test_module.Test # class
test_instance = Test()

如果上面的代码在函数内部,那么将Test放入全局命名空间:globals()['Test'] = Test。请注意,您可能不需要它,并且有更好的方法可以在不修改函数内的全局命名空间的情况下执行任何操作。

不鼓励使用__import__()代替importlib.import_module()

如果知道模块和类的名称,您可以在模块级别编写:

from Test import Test