How Can I Run a Streamlit App from within a Python Script?
Asked Answered
A

6

23

Is there a way to run the command streamlit run APP_NAME.py from within a python script, that might look something like:

import streamlit
streamlit.run("APP_NAME.py")


As the project I'm working on needs to be cross-platform (and packaged), I can't safely rely on a call to os.system(...) or subprocess.

Advocation answered 6/7, 2020 at 17:0 Comment(1)
See ploomber.io/blog/streamlit-from-python .Rondelet
A
24

Hopefully this works for others: I looked into the actual streamlit file in my python/conda bin, and it had these lines:

import re
import sys
from streamlit.cli import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

From here, you can see that running streamlit run APP_NAME.py on the command line is the same (in python) as:

import sys
from streamlit import cli as stcli

if __name__ == '__main__':
    sys.argv = ["streamlit", "run", "APP_NAME.py"]
    sys.exit(stcli.main())

So I put that in another script, and then run that script to run the original app from python, and it seemed to work. I'm not sure how cross-platform this answer is though, as it still relies somewhat on command line args.

Advocation answered 7/7, 2020 at 12:22 Comment(5)
Broken. The streamlit.cli submodule no longer exists as of Streamlit 0.12.0: ImportError: cannot import name 'cli' from 'streamlit' (/usr/lib/python3.10/site-packages/streamlit/__init__.py). Unstable upstream APIs is why we can't have stable StackOverflow answers. </sigh>Basis
Update: the streamlit.cli submodule has been moved to streamlit.web.cli. I can personally verify that the API otherwise appears to be identical. Gah! Why wouldn't Streamlit just add a simple alias from the latter to the former to preserve backward compatibility? That's not a good look in 2022, Streamlit – seriously. Not cool.Basis
Bear in mind it may break again. The streamlit developers consider it internal. See here: discuss.streamlit.io/t/run-streamlit-from-pycharm/21624/3Misuse
Update: from streamlit.web import cli as stcliUrbas
Even with the update from streamlit.web import cli as stcli RuntimeError: asyncio.run() cannot be called from a running event loopTerefah
L
10

You can run your script from python as python my_script.py:

from streamlit.web import cli as stcli
from streamlit import runtime
import sys

if __name__ == '__main__':
    if runtime.exists():
        main()
    else:
        sys.argv = ["streamlit", "run", sys.argv[0]]
        sys.exit(stcli.main())
Largescale answered 13/2, 2021 at 9:55 Comment(4)
While clever, violating privacy encapsulation by directly testing streamlit._is_running_with_streamlit is not a production-hardened solution. The Streamlit API moves rapidly. If this hasn't already broke, it probably will shortly.Basis
@CecilCurry streamlit._is_running_with_streamlit doesn't work anymore now. Do you know the latest update for this?Puglia
You can query the port streamlit runs on and verify that the process matches streamlit: How to check if a network port is open?Execrative
Now there is a better solution: from streamlit import runtime and runtime.exists() instead of streamlit._is_running_with_streamlitMarchand
R
6

I prefer working with subprocess and it makes executing many scripts via another python script very easy.

The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions:

import subprocess
import os

process = subprocess.Popen(["streamlit", "run", os.path.join(
            'application', 'main', 'services', 'streamlit_app.py')])
Routinize answered 1/5, 2021 at 12:15 Comment(1)
subprocess.run("streamlit run app.py") works too, which is now the preferred option, see docs.python.org/3/library/subprocess.html#subprocess.runSite
O
4

With the current streamlit version 1.21.0 the following works:

import streamlit.web.bootstrap
streamlit.web.bootstrap.run("APP_NAME.py", '', [], [])

Execute ?streamlit.web.bootstrap.run do get more info on the different options for streamlit.web.bootstrap.run. For example, you can provide some args to the script.

Overboard answered 28/4, 2023 at 13:25 Comment(1)
This is not recommended by the developers as it uses an internal API (which already moved once). See here: github.com/streamlit/streamlit/issues/…Misuse
U
1
import sys
from streamlit.web import cli as stcli

if __name__ == '__main__':
    sys.argv = ["streamlit", "run", "app.py"]
    sys.exit(stcli.main())
Urbas answered 6/1, 2024 at 12:58 Comment(1)
Hi, Harshit! This question already has a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?Dextrorotation
L
0

A workaround I am using is the following:

  1. Write the streamlit app to the temporary directory of the computer.
  2. Extecute the streamlit app.
  3. Remove the streamlit app again.
import os
import subprocess
import tempfile

def run_streamlit_app(app):
    # create a temporary directory
    temp_dir = tempfile.TemporaryDirectory()
    temp_file_path = os.path.join(temp_dir.name, 'app.py')
    
    # write the streamlit app code to a Python script in the temporary directory
    with open(temp_file_path, 'w') as f:
        f.write(app)
    
    # execute the streamlit app
    try:
        # execute the streamlit app
        subprocess.run(
            ["/opt/homebrew/Caskroom/miniforge/base/envs/machinelearning/bin/streamlit", "run", temp_file_path],
            stderr=subprocess.DEVNULL
        )
    except KeyboardInterrupt:
        pass
    
    # clean up the temporary directory when done
    temp_dir.cleanup()

where an example could look like the following:

app = """
import streamlit as st
import matplotlib.pyplot as plt
import numpy as np

arr = np.random.normal(1, 1, size=100)
fig, ax = plt.subplots()
ax.hist(arr, bins=20)

st.pyplot(fig)
"""
run_streamlit_app(app)
Lorri answered 29/5, 2023 at 14:28 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.