Mahesh
Mahesh

Reputation: 1012

Flask does not serve static html file from exe created using pyInstaller

I am new to python, I have the folder structure as below

|-main.py
|-client
|----index.html
|----scripts

I have created the flask app and set static_folder as client.

app = Flask(__name__, static_url_path="", static_folder='client')

and below is the route

@app.route('/')
def index():
    print("static folder " + app.static_folder)
    return app.send_static_file("index.html")

When I run my app normally then it works and serves the index.html and all scripts.

I have created exe using pyinstaller. When I run the exe, it starts the server but it does not serve the index.html. The print statement writes on the console as "static folder C:\8088\client". 8080 is folder in which I have placed the exe and running from here. If I manually copy the client folder in 8080 directories then it works. I want the HTML should be served from within the exe as I do not want to expose those files.

With pyinstxtractor.py I have extracted and checked that client folder exist in the extracted files.

Am I missing something?

Upvotes: 0

Views: 8263

Answers (2)

Rushikesh Sabde
Rushikesh Sabde

Reputation: 1626

By default, the flask app will look for templates directory in the root folder. There is also the possibility to overwrite Jinja loader and set the paths where Jinja will look for the templates. Like:

my_loader = jinja2.ChoiceLoader([
    app.jinja_loader,
    jinja2.FileSystemLoader(['/flaskapp/userdata', 
                             '/flaskapp/templates']),
])
app.jinja_loader = my_loader

Directories are arranged in the order where Jinja needs to first start looking for it. Then from the view, you can render user-specific template like this:

render_template('%s/template1/hello.html' % username)

Upvotes: 2

Masoud Rahimi
Masoud Rahimi

Reputation: 6051

There are some problems with your code:

  1. You shouldn't use static files to serve HTML files so you need to use Templates. The static files used for serving static files like user files.

  2. When you want to freeze your app you should take care of two things. First, you need to add your files as data-files with Pyinstaller to extract them on temp directory on each run of your app.

    Second, your files should be loaded correctly from the extracted files in temp directory.

Suppose this project tree:

│app.py
│
├───client
│       file.txt
│
└───templates
        index.html

Next, app.py should look like this:

from flask import Flask, render_template
import os
import sys


def resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)


app = Flask(__name__, static_url_path="", static_folder=resource_path(
    'client'), template_folder=resource_path("templates"))


@app.route('/static')
def files():
    return app.send_static_file("file.txt")


@app.route('/')
def index():
    return render_template("index.html")


if __name__ == "__main__":
    app.run(debug=True)

Finally you can use the below command to generate executable, take a note on add-data:

pyinstaller app.py -F --add-data "./templates/*;templates" --add-data "./client/*;client"

Upvotes: 2

Related Questions