How can I include assets of a dash app into an exe file created with pyinstaller --onefile?

I have the same question posted on stackoverflow, but with no answer: python - How can I include assets of a dash app into an exe file created with pyinstaller --onefile? - Stack Overflow

Basically, it seems like dash is unable to access the asset folder in a temp directory. I have the following code to get the temp directory:

# get temp working directory
import sys
import os
def resource_path(relative_path):

# get absolute path to resource
    try:
        # PyInstaller creates a temp folder and stores path in _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

print(resource_path("assets"))

This gives me a the path to the current working directory/assets. It works in an anaconda environment as well when bundling the app into an .exe file, showing me the path where the assets are in the console.

But the next part is where I run into trouble:

# create app
app = dash.Dash(__name__, assets_url_path=resource_path("assets"))

For some reason, this only works in the Anaconda virtual environment, but not when running the code from .exe. The dash app opens just fine, but the css is not loaded from .exe, despite print(resource_path("assets")) showing the temporary path to which I can navigate and see the css file…

What am I missing?

@DataWiz, have you managed to solve this problem? In addition to an assets folder, I have a data folder as well. I still could not manage to successfully create an .exe file. Any input is highly apperciated.

Sorry, I have since abandoned the idea of pyinstaller and dash and moved to a web app. I’d be curious to know if it has become any easier though.

@abeljads did you find a solution? I can package my app without issue, but my css file doesn’t get recognized so clearly packaging the assets folder isn’t working.

I have not got any solution yet. Can you share your code that is working for you without including the asset folder? Thanks in advance.

@abeljads sure! Note that I’m using a windows machine. For Linux I think you just need to replace semi-colons with colons.

I actually did ultimately get it to work! I think the second --add-data option might not be necessary, but its working for me now and I’m not going to change it :slight_smile:

pyinstaller --onefile --hidden-import pyodbc --add-data="assets;assets" --add-data "assets\base.css;assets" --additional-hooks-dir=hooks app.py

You might have to make some changes, like the hidden import command line option.

Importantly, I have a folder in the same directory as the app.py file called “hooks”. In it is a handful of individual .py files. They all follow the same structure, though, and just change the package they’re supporting. I’ll give an example with dash bootstrap components. The name of the file is hook-dash_boostrap_components.pyand the code in the file is below.

# hooks/hook-dash_boostrap_components.py

from PyInstaller.utils.hooks import collect_all

datas, binaries, hiddenimports = collect_all('dash_bootstrap_components')

For my application I had to create these files for dash bootstrap components, dash core components, dash html components, dash renderer, dash table, and flask compress. I determined these were needed via trial and error.

1 Like