Using PyInstaller (or similar) to create an executable

NOTE

The executable file created above does not work alone.
You should copy .streamlit and main.py into dist directory.

Any way to make to the executable work standalone?

We can avoid using .streamlit/config.toml by using

streamlit run main.py --global.developmentMode=false --server.port=8501

But how can we include main.py within the executable to hide the code?

1 Like

Hey Guys thanks for the tutorial and files, sorry I’m a newbie, so I have downloaded the 2 files , and i have changed the “python.exe -m pymedphys gui” by " python.exe -m streamlit run C:/Users/belba/PycharmProjects/MLTEST2/appcopy.py"

the test file is on GitHub - bello7777/Teston: streamlit exe template and work fine with streamlit sharing https://share.streamlit.io/bello7777/teston/main/appcopy.py working

I got this error message related to pyinstaller , any help plsssss

C:\Users\belba\PycharmProjects\MLTEST2\venv\Scripts\python.exe C:/Users/belba/PycharmProjects/MLTEST2/pyinstaller-bundle-script.py
Traceback (most recent call last):
File “C:/Users/belba/PycharmProjects/MLTEST2/pyinstaller-bundle-script.py”, line 94, in
main()
File “C:/Users/belba/PycharmProjects/MLTEST2/pyinstaller-bundle-script.py”, line 49, in main
_install(cwd, installation_path)
File “C:/Users/belba/PycharmProjects/MLTEST2/pyinstaller-bundle-script.py”, line 64, in _install
sys._MEIPASS # pylint: disable = no-member, protected-access
AttributeError: module ‘sys’ has no attribute ‘_MEIPASS’

Process finished with exit code 1

a

Hi @okld,

I suspect that @Belbaly_Nassim is trying to use the work I underwent. Above you mentioned the following:

A benefit of the approach I underwent is it doesn’t let pyinstaller strip out the dependencies, and it is compatible with any Python library (exe creators don’t need to deal with pyinstaller incompatibility).

I don’t currently have the bandwidth to help @Belbaly_Nassim, but might you, @okld, have time to jump on a quick ~30 min video call, where I can describe what I have done and potentially you could carry the baton onwards?

Cheers,
Simon

2 Likes

Any updates on this @okld @SimonBiggs, like @Belbaly_Nassim I also get the same error. Googling looks like it cant make a temporary folder?

A drag drop exe that can do this would be ideal. It’s just beyond my knowledge.

Hey,

@seanbf, not as far as I know.

@SimonBiggs, still working on the matter? Is your work available somewhere on github so I can quickly check the current status?
You can DM me on discourse to organize a call if needed.

Hi @okld,

In fact, I just picked it back up today and gave it a shot. I did hit a dead end though, so if you were interested in further troubleshooting that’d be amazing.

I detailed the steps I was trying out over at:

1 Like

Hi everyone,

I tried the above solution by @hmasdev but I could not make it run yet.
When running pyinstaller --onefile --additional-hooks-dir=./hooks run_main.spec --clean I get the error that the file
‘{$MYCONDAENV}\Lib\site-packages\altair\vegalite\v4\schema\vega-lite-schema.json’
cannot be found.
I checked that the file exists but I think I need to change this part “{$MYCONDAENV}” in the spec file. Should I keep the “$” and the “{}”? Or should I replace {$MYCONDAENV} by the complete path?

EDIT:
After replacing “{$MYCONDAENV}” by the complete path I don’t get the error regarding the file vega-lite-schema.json any more. Now when starting run_main.exe it uses the port 3000 instead of 8501. Any idea what I might miss?

EDIT 2:
It was the “.” in “.streamlit” :confused:
It works now :slight_smile:
The exe file gets pretty big though.

Great job guys, thanks a lot

1 Like

After trying this method on another streamlit app including data analysis tools like pandas and sklearn it turns out that in the executable file all processes are pretty slowed down which makes this method unfortunately not applicable for me :slightly_frowning_face:

Would have been too nice to be true to be able to deploy web apps based on streamlit with this method :grin:

1 Like

Hei guys,
Did anyone manage to include the main.py file as @dracarys3 mentioned?

I managed to get the .exe running but still need all python files but I would like to be able to just share one file.

3 Likes

@SimonBiggs
Hi! I would be interested in a ~30 min video call to get the steps and potentially create a guide step-by-step for our peers. What do you say?

Yup, sounds good. @OneYoungLion has also posted about this over at:

Potentially @OneYoungLion and yourself could both be on the video call?

I think this would be a requirement :slight_smile:

hi, @hmasdev
when i run run_main.exe i get the following error
raceback (most recent call last):
File “run_main.py”, line 4, in
AttributeError: module ‘streamlit.cli’ has no attribute ‘_main_run_clExplicit’
[26348] Failed to execute script ‘run_main’ due to unhandled exception!

although i defined this function in cli.py as follows
def _main_run_clExplicit(file, command_line, args=, flag_options={}):
streamlit._is_running_with_streamlit = True
bootstrap.run(file, command_line, args, flag_options)

someone knows how to solve it?

Wow I had no clue there’s such a massive conversation going on on the very topic I’m interested in figuring out! @SimonBiggs I’d be happy to get on that call please just let me know when and where. Although, fair warning, I’m only useful as your “dummy check”, i.e. “is this simple enough for a dummy to figure out” as the extent of my programming knowledge is far behind everyone else here :smiling_face_with_tear:

On a separate note, and I genuinely hope my tone is not misunderstood, why is this entire process not as easy as just adding a few lines of code at the start of the program? I mean something like:

st.launch_host(ip = “192.168.XX.XX”, port= “8501”)

And maybe have this code replace the entire process of running the cmd “streamlit run XYZ.py” so whenever you run your code, it goes through the entire process? And also, I believe this makes it so just making an exe out of your python would make it a standalone app that launches the server and does all the stuff we are all trying to achieve here?

I mean, in my unprofessional opinion, I just find the whole process of opening a terminal and writing the cmd to launch streamlit somewhat unnecessary. What is the reason that that is required and it cannot be done any other way? I mean I do make a batch file that runs the command automatically, but I’m just tired of forgetting to change the name of the python file when I save my program as a new version, and end up wondering for an hour why every tweak that I made is not showing up before I realize the batch file launched an old version of the code :joy:

1 Like

Hi everyone,

I got this run app.py from the pynsist github repository, I got it to work with pynsist, but sadly I need it to work with pyinstaller instead. I have no idea what I am doing but I tried combining the run app.py from pynsist and hmadevs method (excluding --clean), and almost got a working exe file. The only problem is when I open the exe it creates web browser on an infinite loop. Based on what I have gathered it the problem is from the subproces. So can anyone help me figure this out?

from subprocess import Popen, PIPE, STDOUT
import sys
import time
import webbrowser

def main():

# Getting path to python executable (full path of deployed python on Windows)
executable = sys.executable

path_to_main = os.path.join(os.path.dirname(__file__), "app.py")

# Running streamlit server in a subprocess and writing to log file
proc = Popen(
    [
        executable,
        "-m",
        "streamlit",
        "run",
        path_to_main,
        # The following option appears to be necessary to correctly start the streamlit server,
        # but it should start without it. More investigations should be carried out.
        "--server.headless=true",
        "--global.developmentMode=false",
    ],
    stdin=PIPE,
    stdout=PIPE,
    stderr=STDOUT,
    text=True,
)
proc.stdin.close()

# Force the opening (does not open automatically) of the browser tab after a brief delay to let
# the streamlit server start.
time.sleep(3)
webbrowser.open("http://localhost:8501")

while True:
    s = proc.stdout.read()
    if not s:
        break
    print(s, end="")

proc.wait()

if name == “main”:
main()

For some, the following approach may work well:

It can make sharing a streamlit application as simple as emailing a html file.

2 Likes

Hi @SimonBiggs! Do you have any availability for that video call that was discussed a while ago? To use your method for making an executable?

Yup, for sure. Would both you @OneYoungLion, and @AntonisCSt be able to meet together first, compare notes, detail on here what you have tried, and where you have struggled, as well as formulate some clear questions. Then once you both have helped each other as much as you can, let us three (and any others who are interested) jump on a video call to see how I can help.

Cheers,
Simon

I believe the question has been discussed enough already. Here, on Github, and in our email correspondence a few months ago. In my opinion, this forum, and this thread, would make a great place for you to share your thoughts and the potential solution with the community. Otherwise, I’ll work around the issue or seek the solution elsewhere. This is for a hobby project and I don’t think I should keep the final step hostage anymore. Thanks.

Fair enough :slight_smile:.

The time goes to unpacking the files, since the exe was created with --onefile.