Python跨目录调用yamlCreation函数报ModuleNotFoundError错误
问题原因
触发ModuleNotFoundError: No module named 'bss_micro_svcs'的核心原因是Python模块搜索路径和项目结构不匹配,同时代码里还存在两个会导致后续运行失败的隐藏问题:
- 模块搜索路径错误:执行命令时的工作目录是
~/Desktop/servicelaunchmgr,被运行的kubectl.py位于嵌套的bss_micro_svcs/bss_micro_svcs/目录下,Python默认会将脚本所在目录加入模块搜索路径,该目录下没有名为bss_micro_svcs的子包,自然无法命中导入规则。 - 目标函数未定义:贴出的
templating_to_yaml.py代码全是顶层直接执行的Jinja2渲染逻辑,没有使用def yamlCreation():封装函数,就算导入路径正确,也会抛出找不到yamlCreation属性的错误。 - 硬编码相对路径隐患:代码中写死的模板目录、yaml输出目录都是固定相对路径,只要执行脚本时的工作目录发生变化,就会触发文件不存在的报错。
修复方案
1. 调整项目结构为标准Python包格式
当前项目多嵌套了一层同名bss_micro_svcs目录,先把内层bss_micro_svcs目录下的所有文件(kubectl.py、kubectl_utils文件夹、yamls文件夹)全部剪切到外层bss_micro_svcs目录下,删除空的内层目录。之后在每一层包目录下新建空的__init__.py文件,标识该目录为Python可识别的包,调整后的结构参考:
servicelaunchmgr/ # 命令执行的根目录 └── bss_micro_svcs/ # 顶层业务包 ├── __init__.py # 空文件 ├── kubectl.py ├── kubectl_utils/ │ ├── __init__.py # 空文件 │ └── templating_to_yaml.py └── yamls/ ├── templates/ │ ├── deployment.tmpl │ └── services.tmpl └── services/ └── integration/
2. 改造templating_to_yaml.py
将散落的顶层逻辑封装到yamlCreation函数中,同时替换硬编码路径为基于当前文件位置的动态绝对路径,彻底解决工作目录变化导致的文件找不到问题:
from jinja2 import FileSystemLoader, Environment import os # 动态计算路径,不依赖执行时的工作目录 CURRENT_FILE_PATH = os.path.abspath(__file__) CURRENT_DIR = os.path.dirname(CURRENT_FILE_PATH) TEMPLATE_DIR = os.path.normpath(os.path.join(CURRENT_DIR, '../yamls/templates')) OUTPUT_DIR = os.path.normpath(os.path.join(CURRENT_DIR, '../yamls/services/integration')) def yamlCreation(): env = Environment(loader=FileSystemLoader(TEMPLATE_DIR)) # 渲染deployment配置 deployment_tmpl = env.get_template('deployment.tmpl') deployment_content = deployment_tmpl.render( deployment_name='nginx-deployment', deployment_app='nginx', deployment_replicas='3', deployment_container_name='nginx', deployment_image='nginx:1.14.2', deployment_container_port=80 ) with open(os.path.join(OUTPUT_DIR, 'deployment.yaml'), 'w') as f: f.write(deployment_content) # 渲染service配置 service_tmpl = env.get_template('services.tmpl') service_content = service_tmpl.render( service_name='integration-service', service_name_space='demo-sandbox', service_app='integration', service_port=8090, target_port=8090 ) with open(os.path.join(OUTPUT_DIR, 'services.yaml'), 'w') as f: f.write(service_content)
3. 调整kubectl.py的运行逻辑
在文件开头手动将项目根目录加入Python搜索路径,同时增加主入口判断,避免文件被导入时自动执行业务逻辑:
import sys import os # 将项目根目录加入模块搜索路径 PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, PROJECT_ROOT) from bss_micro_svcs.kubectl_utils.templating_to_yaml import yamlCreation class Kube(Svcs): def startService(self, cluster_info, service, service_profile): yamlCreation() if __name__ == '__main__': k = Kube() k.startService()
调整完成后,进入servicelaunchmgr目录执行脚本即可正常运行。如果运行时提示Jinja2相关导入错误,在虚拟环境中执行pip install jinja2安装依赖即可。
内容的提问来源于stack exchange,提问作者Prince Imam
相关产品推荐
相关产品推荐

