【问题标题】:jinja2.exceptions.TemplateNotFound: color_scale.js in a Pyinsttaller bundled Python-Flask appjinja2.exceptions.TemplateNotFound:Pyinsttaller 捆绑 Python-Flask 应用程序中的 color_scale.js
【发布时间】:2021-09-09 13:05:29
【问题描述】:

该应用程序运行良好,但在尝试运行 Pyinstaller 捆绑的 .exe 文件时,它给了我消息:jinja2.exceptions.TemplateNotFound: color_scale.js

此 .js 文件位于 ...Lib\site-packages\branca\templates 中。我已经在 .spec 文件中插入了相应的关联,以便 Pyinstaller 可以收集它:

a = Analysis(['app.py'],
...
 datas=[(...
...
("C:...\\Lib\\site-packages\\branca\\templates","templates"),
...

以前,我遇到过 ValueError: The 'branca' package is not installed in an PackageLoader 理解的方式,女巫我通过修补 .../site-packages/branca/element.py 来使用 jinja2 解决了这个问题处理冻结的应用程序时使用 .FileSystemLoader 而不是 jinja.PackageLoader:

import sys
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
    import os
    from jinja2 import FileSystemLoader
    bundle_dir = getattr(sys, '_MEIPASS')
    data_dir = os.path.abspath(os.path.join(bundle_dir, 'branca', 'templates'))
    ENV = Environment(loader=FileSystemLoader(data_dir))
else:
    ENV = Environment(loader=PackageLoader('branca', 'templates'))

我正在处理 Python 3.9.6、Flask 1.1.2、Werkzeug 1.0.1 和 Pyinstaller 3.6。

我不知道这种关系,但这个问题不会出现在 32 位旧版本的 bunled 应用程序中。

感谢您的帮助。谢谢!

【问题讨论】:

  • 你应该把它放在 branca/templates 我猜是"C:...\\Lib\\site-packages\\branca\\templates","branca/templates")。另外,您可以使用--collect-data branca 看看是否有效。
  • @gfdsweds 成功了! "C:...\\Lib\\site-packages\\branca\\templates","branca\templates") 解决了这个问题。对于后续问题,我不得不在所有 folium 脚本中使用 FileSystemLoader-PackageLoader 补丁,但现在可以了。谢谢!

标签: python-3.x flask jinja2 pyinstaller


【解决方案1】:

问题

我在尝试使用 pyinstaller 将使用烧瓶文件运行的 app.py 转换为可执行文件时偶然发现了同样的错误。在执行可执行文件后导航到 127.0.0.1:5000(在我的情况下托管应用程序)时,会出现 TemplateNotFoundError。即使应用程序在直接执行 app.py 文件时运行良好。 很难找出烧瓶在哪里寻找它试图加载的模板。我的解决方案更像是一种解决方法,而不是对问题根源的实际修复。我的文件结构看起来像这样:

main_folder
|- web_app
    |-templates  
    |-app.py

我在 main_folder 中执行了 pyinstaller 命令。

找出 Flask 在哪里寻找模板

从 powershell 创建可执行文件时,不要使用 -w 选项。传递此选项将阻止在运行 exe 时打开 cmd 窗口,从而拒绝我们试图查看的输出。在我的例子中,Creation 看起来像这样:

pyinstaller --onefile 'web_app/app.py' --paths='C:\Users\nick\file\to\selfwritten\packages\to\load' --collect-data='web_app.templates'

请务必添加您“动态”加载的任何包,例如通过在运行时将 sys.path 操作到 --paths 选项(根据When sth. goes wrong- pyinstaller documentation)。

此外,您必须告诉flask 您想查看它从哪里加载模板。为了做到这一点,可以将“EXPLAIN_TEMPLATE_LOADING”选项传递给您的烧瓶应用程序。在我的情况下,我将它添加到我的 app.py 文件的开头(以下代码中的第三行)

app = Flask(__name__)
app.config['SECRET_KEY'] = '<your secret key>'
app.config['EXPLAIN_TEMPLATE_LOADING']= True 

做完这两件事后(显然后一件事必须在创建可执行文件之前进行)可以执行创建的exe文件。这样做时,您应该看到一个显示类似输出的 cmd 窗口,如下所示: I am not yet allowed to add the images in post :( 对于它加载的每个模板,都有一些输出还包含它试图在其中找到模板的搜索路径。如您所见,这是一些奇怪的临时路径,默认情况下不包括您的模板。在您的情况下,在查找模板时应该有一些类似“不匹配”的行(上面的屏幕截图是在解决问题后拍摄的)。所以现在我们唯一要做的就是让 pyinstaller 在执行可执行文件时自动将模板添加到该临时文件夹中。

让 pyinstaller 创建正确的临时文件

在找到flask在哪里寻找模板后,我们将不得不删除到目前为止我们创建的可执行文件(为了确保没有缓存任何内容,只需删除使用pyinstaller创建的所有文件和文件夹(dist、build、exe文件和规格文件))。现在我们只需将要加载的模板文件夹添加到我们从中创建 exe 的文件夹中。就我而言,这是 main_folder,它将给我留下以下文件结构:

main_folder
|- templates
|- web_app 
    |-app.py

如果您现在创建 exe,执行它并查看您的临时文件夹(flask 查找模板的文件夹),您将看到添加的模板。现在烧瓶能够找到它们并且一切都像魅力一样工作。我对我的静态文件(css 和 js)做了同样的事情。

尽管如此,这感觉像是一种解决方法。我可以想象告诉烧瓶在其他地方寻找模板(即更改搜索路径)的配置会更优雅。也可以将模板添加为数据或某事。使用 pyinstaller 创建可执行文件时类似。但是,我没有设法实现两者中的任何一个。我希望这也能为您解决问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多