Using a Streamlit app that is part of a CLI package

Using a Streamlit app that is part of a CLI package

I am developing a Python package that has a command-line interface (CLI). The package also contains a Streamlit app as one of its features. To demonstrate this kind of package, I have created an example project that has the layout shown below. The Streamlit app lives in app.py, the CLI is defined in the cli.py module, and the adder.py represents some other functionality in the package that would be imported in the app.py module.

streamlit-pkg/
├── src/
│   └── stpkg/
│       ├── __init__.py
│       ├── adder.py
│       ├── app.py
│       └── cli.py
├── tests/
│   └── test_adder.py
├── pyproject.toml
├── README.md
└── uv.lock

More details of the Python files are given below.

# adder.py

def add(x: float, y: float) -> float:
    """Add two numbers."""
    z = x + y
    return z
# app.py

import streamlit as st
from stpkg.adder import add

def main():
    """Create content for the streamlit app."""

    st.markdown("""
    # Streamlit app

    Hello there!
    """)

    total = add(12, 5.5)
    st.markdown(f"Total is {total}")

if __name__ == "__main__":
    main()
# cli.py

import argparse
import importlib.resources
from streamlit.web import cli

def main():
    """Command line entrypoint for the package."""

    parser = argparse.ArgumentParser(description="CLI package with Streamlit app")
    parser.add_argument("run", help="enter 'go' to run streamlit app")
    args = parser.parse_args()

    if args.run == "go":
        print("Run the Streamlit app ...")

        with importlib.resources.path("stpkg", "app.py") as app_file:
            cli.main_run([str(app_file)])

And here is the pyproject file that defines the CLI entry-point for the package.

# pyproject.toml

[build-system]
requires = ["uv_build>=0.8.11,<0.9.0"]
build-backend = "uv_build"

[project]
name = "stpkg"
version = "0.1.0"
description = "Streamlit app in a package"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "streamlit>=1.48.1",
]

[dependency-groups]
dev = [
    "pytest>=8.4.1",
    "ruff>=0.12.9",
]

[project.scripts]
stpkg = "stpkg.cli:main"

This approach allows me to install the package and run the Streamlit app by just using stpkg go in the terminal. However, to accomplish this I had to use the cli module from streamlit.web which is not documented anywhere in the Streamlit docs. Why is this module not mentioned in the documentation or am I not supposed to use it?

My next question is related to app.py where I import the add function from adder.py. I usually use relative imports inside a Python package like from .adder import add but this doesn’t work with Streamlit. I had to define it as from stpkg.adder import add. Why does a Streamlit app not support relative imports?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.