Python:Dynamic“from”imp

2024-06-16 08:58:02 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我试着把一堆“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

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


Tags: infromimport路径目录foo动态语句
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" 

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

为什么不直接用^{}代替字符串咀嚼呢?然后你得到一个模块的参考。然后,您可以在module对象上使用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

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

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

相关问题 更多 >