如何从子目录的文件中动态导入函数?
如何从子目录的文件中动态导入函数?
看起来你选对了用importlib做动态导入的路子,但遇到了两个小坑导致报错,我帮你一步步搞定~
第一个坑:别把.py后缀带进模块名里
看你的错误提示里出现了subfolder1.subfolder2.file1.py,这说明你输入文件名的时候大概率带了.py后缀!importlib.import_module需要的是模块名,不是完整的文件名,所以得确保输入的是file1而不是file1.py。
当然,为了更友好,你可以在代码里自动处理掉用户不小心输入的后缀:
file = input("Either file1 or file2").strip().removesuffix('.py')
这样不管用户输不带后缀的file1还是带后缀的file1.py,代码都能正常处理。
第二个坑:让子目录变成Python可识别的包
错误里还提到'subfolder1.subfolder2.file1' is not a package!,其实问题出在父目录没有被Python当作“包”。在Python中,要让一个目录被识别为包,只需要在目录里放一个空的__init__.py文件就行。
你需要在这两个目录里分别创建:
subfolder1/__init__.py(空文件就可以,不用写任何代码)subfolder1/subfolder2/__init__.py(同样空文件就行)
这样Python就会把这些目录当作合法的包,importlib就能正确找到里面的模块了。
优化后的完整代码
我帮你把代码再完善一下,加了输入验证和函数存在性检查,更健壮:
import importlib import os # 自动扫描subfolder2里所有可运行的文件(不用手动维护白名单!) subfolder_path = os.path.join(os.path.dirname(__file__), "subfolder1", "subfolder2") allowed_files = { f[:-3] for f in os.listdir(subfolder_path) if f.endswith(".py") and not f.startswith("_") # 排除__init__.py和下划线开头的文件 } file = input(f"Enter file name (choose from: {', '.join(allowed_files)}): ").strip().removesuffix('.py') if file not in allowed_files: print(f"[ERROR] Invalid file! Choose from: {', '.join(allowed_files)}") else: try: mod = importlib.import_module(f"subfolder1.subfolder2.{file}") except Exception as error: print(f"[ERROR] Failed to import module: {error}!") else: if hasattr(mod, "run"): mod.run() else: print(f"[ERROR] The file {file}.py doesn't have a 'run()' function!")
额外福利:自动适配新增文件
上面的代码已经实现了自动扫描subfolder2里的Python文件,以后你每天加新文件进去,完全不用修改主代码,也不用加if判断,程序自动就能识别并允许用户选择运行,完美匹配你的需求~
现在按照这个配置,创建好__init__.py文件,输入正确的文件名,就能顺利运行run函数啦!
备注:内容来源于stack exchange,提问作者GalaxyGamerYT
相关产品推荐
相关产品推荐

