【问题标题】:Python: Dynamic "from" importPython:动态“从”导入
【发布时间】:2012-06-21 22:40:11
【问题描述】:

所以我试图把一堆“from x import x”语句变成这样:

from class_foo import class_foo

变成动态的东西。我正在尝试将路径传递到目录并让它导入其中的所有模块。

def dynamicImport(dirPath):
    filez = os.listdir(dirPath)
    for file in filez:
        if "class" in file:
            oname = file[:-3] #cut off the file extension, trivial

            imp_statement = "from " + oname + " import " + oname
            #when I print imp_statement, I can verify it's being concatenated correctly

            exec(imp_statement)

当我运行这个函数并传递一个路径时,语句字符串被正确创建并且它不会产生错误,但稍后我将尝试访问其中一个导入的对象,并且发生这种情况:

foo = class_foo()

NameError: name 'class_foo' is not defined

显然我做错了什么。任何帮助将不胜感激。

【问题讨论】:

标签: python


【解决方案1】:

您在函数的本地命名空间中 execing 导入语句,因此这是定义名称的地方。当函数结束时,这个命名空间就消失了,你什么都没有了。你可能想要的是exec imp_statement in globals()

为什么不直接使用__import__() 而不是字符串处理?然后你会得到一个对你的模块的引用。然后,您可以在模块对象上使用 getattr() 提取类引用并将其插入到 globals() 中(或者只需将字典传回给调用者,然后调用者可以使用它来执行 globals().update())。

import sys, os

def getClasses(directory):
    classes = {}
    oldcwd = os.getcwd()
    os.chdir(directory)   # change working directory so we know import will work
    for filename in os.listdir(directory):
        if filename.endswith(".py"):
            modname = filename[:-3]
            classes[modname] = getattr(__import__(modname), modname)
    os.setcwd(oldcwd)
    return classes

globals().update(getClasses(r"C:\plugin_classes"))

类似的东西。或者不要使用您的模块更新globals(),这可能会破坏您关心的全局变量,只需将类留在字典中并从那里引用它们:

classes = getClasess(r"C:\plugin_classes")
for clas in classes.itervalues():
    instance = clas(1, 2, 3)       # instantiate
    instance.dosomething_cool(42)  # call method

【讨论】:

  • 您可以使用 fromlist 关键字 arg 并提供您有兴趣检索的属性列表,而不是使用 getattr
  • 哇,谢谢。 __import__ 把我搞糊涂了,因为我没有意识到你可以使用 getattr 来从模块本身中提取类。谢谢一百万!
  • @mvanveen:不幸的是,fromlist 关键字 arg 似乎并没有真正做到你想要的。它仍然给了我对该模块的引用。
【解决方案2】:

Python >= 2.7 有importlib(您可以pip install importlib 在早期版本的python 中使用importlib)

module = importlib.import_module("path.to.module")
MyClass = module.MyClass

【讨论】:

    【解决方案3】:

    假设您的目录结构如下所示:

    ./   <- you are here
    - main.py
    - my_package/
        - __init__.py
        - my_module.py
    

    并且您想动态导入my_module.py,以使用它的一些函数、类等等。然后,使用importlib,可以在main.py中使用如下代码:

    import importlib
    
    pack = "my_package"
    mod = "my_module"
    
    module = importlib.import_module("." + mod, pack)
    # or, alternatively
    module = importlib.import_module(".".join(pack, mod))
    
    module.func("hello") # if my_package/my_module.py defines function "func"
    obj = module.MyClass("world") # if my_package/my_module.py defines class "MyClass" 
    

    【讨论】:

      【解决方案4】:

      我已经很久没有使用 Python 了。但我认为你的问题可能在于“oname”是一个字符串。 from class_foo import class_foo 行不是字符串。一个艰苦的选择是让您的代码创建一个全新的 .py 文件,该文件将包含所有导入。因此,您可以将所有当前文件以及新导入基本上写入以 .py 结尾的文本文件

      【讨论】:

        【解决方案5】:

        看看__import__函数

        【讨论】:

        • 请查看添加示例代码,而不仅仅是提供链接
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-13
        • 2013-03-25
        • 1970-01-01
        • 2011-04-17
        • 2016-10-19
        • 2012-01-10
        • 1970-01-01
        相关资源
        最近更新 更多