1

我现在使用 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

4 回答 4

3

对于更接近您意图的解决方案:

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__上面的代码 /will/ 会破坏您的命名空间,这会很激烈。要么确保你定义__all__,要么修改allImports()为只导入你想要的东西。(例如,仅类,或仅在模块中定义的类。这部分实际上取决于您的用例。)

于 2012-07-05T13:15:24.270 回答
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__()不鼓励使用ofimportlib.import_module()代替。

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

from Test import Test
于 2012-07-05T13:52:15.600 回答
1

使用__import__()加载模块时,您必须在以下位置查找它sys.modules

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

更多信息请参见文档此处此处此处

于 2012-07-05T13:09:37.503 回答
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>
于 2012-07-05T13:03:35.930 回答