Multi-script apps
Real-world applications often span multiple files. This page shows how to build FastAPI and Streamlit apps with multiple Python files.
FastAPI multi-script app
Project structure
project/
├── app.py # Main FastAPI app file
└── module.py # Helper moduleExample: Multi-file FastAPI app
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "flyte>=2.0.0b52",
# "fastapi",
# ]
# ///
"""Multi-file FastAPI app example."""
from fastapi import FastAPI
from module import function # Import from another file
import pathlib
import flyte
from flyte.app.extras import FastAPIAppEnvironment
app = FastAPI(title="Multi-file FastAPI Demo")
app_env = FastAPIAppEnvironment(
name="fastapi-multi-file",
app=app,
image=flyte.Image.from_debian_base(python_version=(3, 12)).with_pip_packages(
"fastapi",
"uvicorn",
),
resources=flyte.Resources(cpu=1, memory="512Mi"),
requires_auth=False,
# FastAPIAppEnvironment automatically includes necessary files
# But you can also specify explicitly:
# include=["app.py", "module.py"],
)
@app.get("/")
async def root():
return function() # Uses function from module.py
if __name__ == "__main__":
flyte.init_from_config(root_dir=pathlib.Path(__file__).parent)
app_deployment = flyte.deploy(app_env)
print(f"Deployed: {app_deployment[0].summary_repr()}")
def function():
"""Helper function used by the FastAPI app."""
return {"message": "Hello from module.py!"}
Automatic file discovery
FastAPIAppEnvironment automatically discovers and includes the necessary files by analyzing your imports. However, if you have files that aren’t automatically detected (like configuration files or data files), you can explicitly include them:
app_env = FastAPIAppEnvironment(
name="fastapi-with-config",
app=app,
include=["app.py", "module.py", "config.yaml"], # Explicit includes
# ...
)Streamlit multi-script app
Project structure
project/
├── main.py # Main Streamlit app
├── utils.py # Utility functions
└── components.py # Reusable componentsExample: Multi-file Streamlit app
all_columns = ["Apples", "Orange", "Pineapple"]
with st.container(border=True):
columns = st.multiselect("Columns", all_columns, default=all_columns)
all_data = st.cache_data(generate_data)(columns=all_columns, seed=101)
data = all_data[columns]
tab1, tab2 = st.tabs(["Chart", "Dataframe"])
tab1.line_chart(data, height=250)
tab2.dataframe(data, height=250, use_container_width=True)
st.write(f"Environment: {os.environ}")
import numpy as np
import pandas as pd
def generate_data(columns: list[str], seed: int = 42):
rng = np.random.default_rng(seed)
data = pd.DataFrame(rng.random(size=(20, len(columns))), columns=columns)
return data
Deploying multi-file Streamlit app
image = flyte.Image.from_debian_base(python_version=(3, 12)).with_pip_packages(
"streamlit==1.41.1",
"pandas==2.2.3",
"numpy==2.2.3",
)
app_env = flyte.app.AppEnvironment(
name="streamlit-multi-file-app",
image=image,
args="streamlit run main.py --server.port 8080",
port=8080,
include=["main.py", "utils.py"], # Include your app files
resources=flyte.Resources(cpu="1", memory="1Gi"),
requires_auth=False,
)
Complex multi-file example
Here’s a more complex example with multiple modules:
Project structure
project/
├── app.py
├── models/
│ ├── __init__.py
│ └── user.py
├── services/
│ ├── __init__.py
│ └── auth.py
└── utils/
├── __init__.py
└── helpers.pyExample code
app = FastAPI(title="Complex Multi-file App")
@app.get("/users/{user_id}")
async def get_user(user_id: int):
user = User(id=user_id, name="John Doe")
return format_response(user)
def authenticate(token: str) -> bool:
"""Authenticate a user by token."""
# ... authentication logic ...
return True
def format_response(data):
"""Format a response with standard structure."""
return {"data": data, "status": "success"}
Deploying complex app
app_env = FastAPIAppEnvironment(
name="complex-app",
app=app,
image=flyte.Image.from_debian_base(python_version=(3, 12)).with_pip_packages(
"fastapi",
"uvicorn",
"pydantic",
),
# Include all necessary files
include=[
"app.py",
"models/",
"services/",
"utils/",
],
resources=flyte.Resources(cpu=1, memory="512Mi"),
)
Best practices
- Use explicit includes: For Streamlit apps, explicitly list all files in
include - Automatic discovery: For FastAPI apps,
FastAPIAppEnvironmenthandles most cases automatically - Organize modules: Use proper Python package structure with
__init__.pyfiles - Test locally: Test your multi-file app locally before deploying
- Include all dependencies: Include all files that your app imports
Troubleshooting
Import errors:
- Verify all files are included in the
includeparameter - Check that file paths are correct (relative to app definition file)
- Ensure
__init__.pyfiles are included for packages
Module not found:
- Add missing files to the
includelist - Check that import paths match the file structure
- Verify that the image includes all necessary packages
File not found at runtime:
- Ensure all referenced files are included
- Check mount paths for file/directory inputs
- Verify file paths are relative to the app root directory