如何动态从给定目录和所有子目录导入所有* .py文件?

格伦·巴克

假设我在一个公共目录下有一堆Python文件,但是在其中,可以存在任意数量的子目录:

/first/foo.py
/first/bar.py
/first/fizz/buzz.py
/first/numbers/one.py
/first/numbers/two.py

我有一些任意文件要导入所有这些文件。手动地,我可以做:

import first.foo
import first.bar
import first.fizz.buzz
import first.numbers.one
import first.numbers.two

但是相反,我希望能够执行以下操作:

import_everything_under('first')

我知道已经出现了类似的问题:从所有文件夹递归导入所有.py文件

但是给出的答案和所谓的重复项无法回答这个问题。


该问题被标记为可能的重复项:如何在文件夹中加载所有模块?

同样,这不能回答这个问题。该问题的答案不是递归的-它只会从直接目录中导入项目,并且不会在子目录中包含脚本,这是我的用例所需要的。

语法void支持Monica

从我的角度来看,您的问题分为两个步骤:

  1. 浏览目录和子目录,找到要导入的所有.py文件的名称

  2. 导入它们!

为了解决(1),我们可以使用该os.walk方法查找所有.py文件。该函数如下所示:

import os
def get_py_files(src):
    cwd = os.getcwd() # Current Working directory
    py_files = [] 
    for root, dirs, files in os.walk(src):
        for file in files:
            if file.endswith(".py"):
                py_files.append(os.path.join(cwd, root, file))
    return py_files

现在您有了.py文件的列表,我们需要一个可以动态导入它们的函数。

import importlib
def dynamic_import(module_name, py_path):
    module_spec = importlib.util.spec_from_file_location(module_name, py_path)
    module = importlib.util.module_from_spec(module_spec)
    module_spec.loader.exec_module(module)
    return module

现在,我们只需要将它们放在一起,编写一个调用您的get_py_files函数的函数,然后遍历结果,并使用加载模块dynamic_import

我假设您希望在python脚本中使用的模块名称与文件名相同,但是可以通过module_name在下面的函数中修改变量来更改它

def dynamic_import_from_src(src, star_import = False):
    my_py_files = get_py_files(src)
    for py_file in my_py_files:
        module_name = os.path.split(py_file)[-1].strip(".py")
        imported_module = dynamic_import(module_name, py_file)
        if star_import:
            for obj in dir(imported_module):
                globals()[obj] = imported_module.__dict__[obj]
        else:
            globals()[module_name] = imported_module
    return

注意,我们必须调用globals()将模块添加到全局名称空间。不这样做,模块将被导入,但是您将无法访问其中的任何内容。如果希望将其作为星号导入star_import = Truedynamic_import_from_src可以传递(例如from first.foo import *。请注意,这可能会覆盖名称空间中的变量,但这仍然是使用*导入的弊端之一

将所有内容扔在一块,以便一次查看全部内容更加容易:

import os
import importlib


def get_py_files(src):
    cwd = os.getcwd() # Current Working directory
    py_files = [] 
    for root, dirs, files in os.walk(src):
        for file in files:
            if file.endswith(".py"):
                py_files.append(os.path.join(cwd, root, file))
    return py_files


def dynamic_import(module_name, py_path):
    module_spec = importlib.util.spec_from_file_location(module_name, py_path)
    module = importlib.util.module_from_spec(module_spec)
    module_spec.loader.exec_module(module)
    return module


def dynamic_import_from_src(src, star_import = False):
    my_py_files = get_py_files(src)
    for py_file in my_py_files:
        module_name = os.path.split(py_file)[-1].strip(".py")
        imported_module = dynamic_import(module_name, py_file)
        if star_import:
            for obj in dir(imported_module):
                globals()[obj] = imported_module.__dict__[obj]
        else:
            globals()[module_name] = imported_module
    return

if __name__ == "__main__":
    dynamic_import_from_src("first", star_import = False)

此时,您可以像导入一样完全访问导入的模块import first.whatever例如,如果first/numbers/one.py包含x=1,则可以说来访问它one.x

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何删除所有子目录中具有给定名称的所有文件?

如何从特定给定的目录和所有子目录中搜索具有特定扩展名的文件

如何使用vim打开当前目录和所有子目录中的所有文件?

如何排除除所有顶级点文件和子目录之外的所有内容?

如何建立目录中所有文件的索引,包括子目录和ZIP文件的内容?

从目录和所有子目录获取所有文件,但不包含一个子目录

如何在Windows中的目录和子目录中查找所有头文件

如何重命名(取消隐藏)目录中的所有文件和子目录?

如何在php中列出目录,子目录和所有文件

所有文件和子目录的循环 cat 命令

如何删除Windows中与给定通配符匹配的子目录中的所有文件?

如何遍历所有子目录中的文件?

如何报告所有子目录中的文件数?

如何在python中包含给定路径中的所有文件以及子目录的所有文件?

解析目录和所有子目录中的所有XML文件

如何更改目录/所有子目录中所有文件的x00权限?

给定父目录的所有子目录中的zip文件

列出给定开始目录中子目录中的所有文件

如何在不删除bash目录的情况下删除目录中的所有文件和子目录?

从目录复制所有文件,而不创建子目录

查找目录及其子目录中的所有文件

如何从某个目录中删除所有文件,但该目录的子目录除外?

如何在匹配模式和替换模式的子目录中查找所有文件

如何删除Bash中的所有文件和子目录(包括边缘情况)

搜索和重命名和MV所有目录和子目录中的文件

如何下载包含在线文件/文件夹列表中的所有文件和子目录的HTTP目录?

如何更改当前目录,子目录以及子目录的子目录中的文件所有权?

如何使用#ifdef和#endif注释掉目录和子目录中所有文件中的垂直线?

如何列出所有文件,但只能列出没有子目录的目录?