Приложение Flask, созданное с помощью pyinstaller, не отрисовки index.html
Я написал приложение с флягой, и он отлично работает. Я хотел распространять его как исполняемый файл.
Пробовал делать это с помощью pyinstaller flaskScript.py
папка dist создана.
Зашел в папку dist и дважды щелкнул мой исполняемый флажок, он запустил мой сервер.
При доступе к URL-адресу localhost: 9090 он дает следующее исключение
jinja2.exceptions.TemplateNotFound
TemplateNotFound: index.html
Traceback (most recent call last)
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1836, in __call__
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1820, in wsgi_app
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1403, in handle_exception
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1817, in wsgi_app
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1477, in full_dispatch_request
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1381, in handle_user_exception
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1475, in full_dispatch_request
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.app", line 1461, in dispatch_request
File "<string>", line 13, in index
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.templating", line 127, in render_template
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/jinja2.environment", line 851, in get_or_select_template
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/jinja2.environment", line 812, in get_template
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/jinja2.environment", line 774, in _load_template
File "/Users/george/Downloads/flaskApps/flaskScript/build/flaskScript/out00-PYZ.pyz/flask.templating", line 64, in get_source
TemplateNotFound: index.html
Пока он отлично работает в настройках dev при выполнении python flaskScript.py
Ответы
Ответ 1
Этот вопрос уже устарел, но у меня возникла та же проблема (Python 3.4.3, Flask 0.10.1 и PyInstaller 3.1.1) при упаковке его в один файл.
Мне удалось решить эту проблему, добавив следующее в скрипт инициализации (app\__init__.py
):
import sys
import os
from flask import Flask
# Other imports
if getattr(sys, 'frozen', False):
template_folder = os.path.join(sys._MEIPASS, 'templates')
app = Flask(__name__, template_folder=template_folder)
else:
app = Flask(__name__)
# etc
Проблема в том, что когда сайт работает в упакованном виде, шаблоны находятся в каталоге с именем _MEIxxxxxx в каталоге temp (см. Это в Руководстве по PyInstaller), поэтому мы должны сообщить об этом Flask.
Это делается с помощью аргумента template_folder
(о котором я узнал в этом ответе здесь и позже в документации по API).
Наконец, есть if
чтобы гарантировать, что мы все еще можем использовать его без упаковки во время его разработки. Если он frozen
, то скрипт упакован, и мы должны сообщить Flask, где найти шаблоны; в противном случае мы запускаем его в среде Python (взято отсюда), и настройки по умолчанию будут работать (если, конечно, вы используете стандартную директорию templates
).
Ответ 2
if getattr(sys, 'frozen', False):
template_folder = os.path.join(sys.executable, '..','templates')
static_folder = os.path.join(sys.executable, '..','static')
app = Flask(__name__, template_folder = template_folder,\
static_folder = static_folder)
скопируйте этот код и вставьте его в свой файл. теперь pyinstaller ищет статическую папку и папку шаблонов в вашем каталоге dist. Теперь скопируйте и вставьте статическую и шаблонную папку в папку dist. он будет работать
Ответ 3
Если вы пытаетесь создать исполняемый файл --onefile, вам также необходимо добавить каталоги в файл спецификации.
-
В коде Python найдите, где работает приложение, и сохраните путь в base_dir
:
import os, sys
base_dir = '.'
if hasattr(sys, '_MEIPASS'):
base_dir = os.path.join(sys._MEIPASS)
-
Передайте правильные пути к приложению Flask, используя параметры static_folder и template_folder:
app = Flask(__name__,
static_folder=os.path.join(base_dir, 'static'),
template_folder=os.path.join(base_dir, 'templates'))
-
В spec файле нам нужно указать pyinstaller, чтобы он включал templates
и static
папку, включая соответствующие папки в разделе Analysis в pyinstaller:
a = Analysis(
...
datas=[
('PATH_TO_THE_APP\\static\\', 'static'),
('PATH_TO_THE_APP\\templates\\', 'templates'),
],
...
Немного объяснения:
Общая проблема с отсутствием поиска файлов после упаковки с помощью pyinstaller заключается в том, что файлы изменят свой путь. С --onefile
ваши файлы будут сжаты внутри exe. Когда вы запускаете исполняемый файл, они распаковываются и помещаются во временную папку.
Это где-то меняется каждый раз, когда вы запускаете файл, но работающее приложение (не файл spec
, а ваш основной файл python, скажем main.py
) можно найти здесь:
import os
os.path.join(sys._MEIPASS)
Таким образом, файлы шаблонов будут не в ./templates
, а в os.path.join(os.path.join(sys._MEIPASS), templates)
. Проблема в том, что ваш код не будет работать, пока он не упакован. Поэтому python main.py
не будет работать.
Поэтому необходимо условие, чтобы найти файлы в нужном месте:
import os, sys
base_dir = '.'
if hasattr(sys, '_MEIPASS'): # or, untested: if getattr(sys, 'frozen', False):
base_dir = os.path.join(sys._MEIPASS)
Более подробная информация о времени выполнения в pyinstaller
Ответ 4
Я только что написал сообщение в блоге об этой проблеме и другие похожие, Создайте один исполняемый файл для приложения Flask с PyInstaller
В основном элегантное решение состоит в следующем:
Окна
pyinstaller -w -F --add-data "templates;templates" --add-data "static;static" app.py
Linux (NOT TESTED)
pyinstaller -w -F --add-data "templates:templates" --add-data "static:static" app.py
Ответ 5
если вы строите из файла .spec, это может быть легко выполнено без изменения
__int__.py
1) добавьте ваши шаблоны и статическую папку к данным в .spec
2) обязательно добавьте jinja2 в hiddenimports
block_cipher = None
# add templates and static folders to a list
added_files =[
('templates/*.html', 'templates'),
('static/*.css', 'static'),
]
a = Analysis(['run.py'],
pathex=['/your/app/location'],
binaries=[],
datas = added_files, # set datas = added_files list
hiddenimports=['jinja2.ext'], # be sure to add jinja2
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
...
этот метод прямо из документации по pyinstaller здесь