您的问题分为两个步骤(从我的角度来看):
浏览您的目录和子目录,找到您要导入的所有 .py 文件的名称
导入它们!
为了解决(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 = True 传递给 dynamic_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 来访问它。