使用Jinja2的PackageLoader渲染模板时脚本重复执行两次的问题
使用Jinja2的PackageLoader渲染模板时脚本重复执行两次的问题
这个问题我之前也踩过坑!核心原因其实是Python模块导入的机制加上你没给脚本加执行防护导致的,咱们一步步理清楚:
为什么会重复执行?
你用PackageLoader('basic')的时候,Jinja2会让Python去导入名为basic的模块——也就是你的basic.py脚本。而如果你的脚本里没有任何执行防护代码,当它被当作模块导入时,整个脚本的代码会从头到尾跑一遍,相当于你直接运行脚本的同时,又被自己导入执行了一次,所以才会出现模板渲染两次的情况。
你用空的other_script.py能正常工作,是因为导入这个模块时,里面没有任何执行逻辑,自然不会触发额外的模板渲染。
两种靠谱的解决方法
方法1:给脚本加上if __name__ == '__main__':防护
这是Python脚本的标准实践,能精准区分“直接运行脚本”和“作为模块被导入”两种场景。把你的执行逻辑放到这个判断里,这样当basic.py被PackageLoader导入时,只会加载函数/变量定义,不会执行渲染和打印的逻辑。
修改后的basic.py代码:
#!/usr/bin/env python3 from jinja2 import Environment, PackageLoader, select_autoescape def render_my_template(): env = Environment( loader=PackageLoader('basic'), autoescape=select_autoescape() ) return env.get_template('basic_template.md').render({'version': 'version123', 'date': 'some-date'}) # 只有直接运行这个脚本时,才会执行下面的代码 if __name__ == '__main__': print(render_my_template())
方法2:改用FileSystemLoader替代PackageLoader
如果你的场景里不需要用Python包的方式来加载模板,直接用FileSystemLoader指定模板目录的绝对路径会更直观,也完全避开模块导入的问题,在CI环境里这种方式有时候反而更可控,因为你可以明确指定模板的位置,不用担心包结构的影响。
修改后的代码示例:
#!/usr/bin/env python3 from jinja2 import Environment, FileSystemLoader, select_autoescape import os # 获取当前脚本所在的绝对目录(避免CI环境中相对路径失效的问题) current_script_dir = os.path.dirname(os.path.abspath(__file__)) # 拼接templates目录的路径 templates_path = os.path.join(current_script_dir, 'templates') env = Environment( loader=FileSystemLoader(templates_path), autoescape=select_autoescape() ) print(env.get_template('basic_template.md').render({'version': 'version123', 'date': 'some-date'}))
这两种方法都能完美解决你遇到的重复执行问题,你可以根据自己的项目结构和CI环境选择更合适的一种~
备注:内容来源于stack exchange,提问作者jeremywat
相关产品推荐
相关产品推荐

