如何仅用Python调用文件夹内所有脚本的指定函数(无需显式导入)
如何用纯Python批量调用指定文件夹内脚本的特定函数?
当然可以!完全用纯Python就能搞定这个需求——不用写任何bash脚本,也不用挨个手动导入每个模块。下面给你两种可行的实现方式,其中用类的方式会更优雅、易维护~
方法一:基于动态导入的函数式实现
这种方式直接利用Python的importlib和os模块动态遍历并导入模块,完全贴合你给出的示例结构。
步骤1:配置modules/__init__.py
在modules文件夹下创建一个空的__init__.py(Python 3.3+其实可以省略,但加上能更好兼容旧版本),然后把下面的代码写进去:
import os import importlib def some_magic_function(): # 获取当前模块文件夹的绝对路径 module_dir = os.path.dirname(__file__) # 遍历文件夹下的所有文件 for filename in os.listdir(module_dir): # 过滤掉__init__.py和非Python文件 if filename.endswith('.py') and filename != '__init__.py': # 去掉.py后缀,得到模块名称 module_name = filename[:-3] # 动态导入模块:格式为「modules.模块名」 module = importlib.import_module(f'.{module_name}', package='modules') # 检查模块是否包含我们需要的可调用函数,避免误触发内部函数 if hasattr(module, 'generic_function') and callable(getattr(module, 'generic_function')): yield module
步骤2:编写main.py
直接按照你给出的示例逻辑编写即可:
import modules import os for module in modules.some_magic_function(): module.generic_function(os.path.basename(__file__))
为什么这样可行?
- 用
os.listdir自动遍历modules文件夹,无需手动声明每个模块 - 用
importlib.import_module动态导入模块,替代了繁琐的逐个导入语句 - 通过
hasattr和callable做校验,确保只调用generic_function,完全不会触发internal_function - 用生成器
yield返回模块,节省内存开销(尤其是模块数量较多时)
方法二:更优雅的面向对象实现
如果想让代码更结构化、易扩展,用类的方式会更合适——我们可以通过基类统一接口,后续维护和扩展会更轻松。
步骤1:修改modules/__init__.py
这次我们在__init__.py里定义一个基类,同时保留动态遍历的逻辑:
import os import importlib class BaseModule: # 定义基类,统一公共方法的接口 pass def some_magic_function(): module_dir = os.path.dirname(__file__) for filename in os.listdir(module_dir): if filename.endswith('.py') and filename != '__init__.py': module_name = filename[:-3] module = importlib.import_module(f'.{module_name}', package='modules') # 遍历模块内的类,找到继承自BaseModule的子类 for name, cls in module.__dict__.items(): if isinstance(cls, type) and issubclass(cls, BaseModule) and cls != BaseModule: # 返回类的实例 yield cls()
步骤2:修改每个moduleX.py
把原来的函数改成继承自BaseModule的类:
import os from modules import BaseModule class Module1(BaseModule): def generic_function(self, caller): print(f'{os.path.basename(__file__)} was called by {caller}') def internal_function(self): print('ERROR: Someone called an internal function')
(注意把Module1换成对应模块的名称,比如module2.py里写Module2)
步骤3:编写main.py
和之前的逻辑几乎一致,只是现在调用的是类实例的方法:
import modules import os for module_instance in modules.some_magic_function(): module_instance.generic_function(os.path.basename(__file__))
类实现的优势
- 用基类统一接口,后续如果要新增公共方法,直接在
BaseModule里定义即可 - 可以借助
abc模块把BaseModule改成抽象类,强制每个模块必须实现generic_function,避免遗漏 - 面向对象的结构更清晰,代码可读性和可维护性更强
内容的提问来源于stack exchange,提问作者JuanP. Zuniga
相关产品推荐
相关产品推荐

