Using PyInstaller (or similar) to create an executable

Hi, Luyutin,

May I contact you? I also from Taiwan and wandering know how to use Pyinstaller to pack streamlit project.

Masaz

Hello! I’ve been scrolling through this thread for a few days since it’s been very useful throughout my development process. I wanted to share how my setup looks like for reference, deriving from hmasdev solution and jvcs 's guide.

Directory

WORKINGDIR
    - program.exe
    - .streamlit/   # my program requires secrets.toml
    - PROGRAMDIR/
        - .venv/ ...
        - dist/
            - program/
                - toc files
        - hooks/
            - hook-streamlit.py
        - resources/
            - icon.png
        - src/
            - main.py
        - build.ps1
        - run_main.py
        - program.spec

build.ps1

.venv/Scripts/Activate.ps1
clear
pyinstaller --onefile -n "program" -i "./resources/icon.png" --hiddenimport ... --additional-hooks-dir=./hooks --workpath ./dist --distpath "../" --add-data "./src:./program/src" run_main.py --clean
& "../program.exe"
  • gave my program a new name and an icon
  • for the longest time, I was stuck trying to get my venv dependencies involved, hence the --hiddenimport ... tag
  • I often came across this issue when trying to run spec files. Hence I worked around it by adding the datas in the command itself through the --add-data tag, meaning I don’t touch the .spec file
  • Since I wanted my .exe file outside the program file, I used the --distpath "../" tag to output at WORKINGDIR instead of PROGRAMDIR
  • --workpath ./dist to keep all working build files in somewhere organised
  • Since I wanted to clean up my folders, added my source files in \src\ and referenced it in --add-data

run_main.py (Dkdatascientist 's solution)

import os
import streamlit.web.bootstrap

if __name__ == "__main__":
    os.chdir(os.path.dirname(__file__))

    flag_options = {
        "server.port": 8501,
        "global.developmentMode": False,
    }

    streamlit.web.bootstrap.load_config_options(flag_options=flag_options)
    flag_options["_is_running_with_streamlit"] = True
    streamlit.web.bootstrap.run(
        ".\src\main.py",
        False,
        ['run'],
        flag_options,
    )
  • This makes it so that you don’t have to write the_main_run_clExplicit() magic function in streamlit.web.cli

hooks/hook-streamlit.py (Jason7 's solution)

from PyInstaller.utils.hooks import collect_all
datas, binaries, hiddenimports = collect_all('streamlit', include_py_files=False, include_datas=['**/*.*'])

Things I want to improve:

  • Not sure if there’s a way to add all the modules/imports from venv instead of manually adding each one in the command as --hiddenimport
  • Want to find a way to move .streamlit back to the PROGRAMDIR instead of the WORKINGDIR