Code Examples: Turning Python Scripts Into Production Systems
This post is the practical companion.
Here, we’ll walk through concrete examples that show the transition
From: Script-style code To production-ready structure
❌ Tutorial Version
pip install requests python app.py
That’s fine for learning. It’s chaos in production.
✅ Production Version
python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txt requirements.txt requests==2.31.0 python-dotenv==1.0.1
Better yet, use pyproject.toml:
[project] name = "order-service" version = "0.1.0" dependencies = [ "requests==2.31.0", "python-dotenv==1.0.1" ]
Why this matters: Production is about determinism. Same dependencies. Same versions. Same behavior.
2️⃣ Stop Using print() — Start Logging
❌ Script Style print("Fetching data...") data = fetch_data() print("Done.")
✅ Production Style
import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" ) logger = logging.getLogger(__name__) logger.info("Fetching data...") data = fetch_data() logger.info("Fetch completed successfully.")
Now you can:
- Send logs to files
- Send logs to monitoring systems
- Control verbosity per environment
- Debug production failures properly
That’s not optional at scale.
3️⃣ Error Handling: Fail Loudly, Fail Intentionally
❌ Tutorial Version
response = requests.get(url) data = response.json()
✅ Production Version
import requests def fetch_json(url: str) -> dict: try: response = requests.get(url, timeout=5) response.raise_for_status() return response.json() except requests.Timeout: raise RuntimeError("Request timed out") except requests.HTTPError as e: raise RuntimeError(f"HTTP error: {e.response.status_code}") except requests.RequestException as e: raise RuntimeError(f"Unexpected request failure: {e}")
-
Production code:
- Sets timeouts
- Raises meaningful errors
- Avoids silent failure
- Makes debugging possible
4️⃣ Configuration Should Not Live in Your Code
❌ Hardcoded Secrets
API_KEY = "sk_live_abc123" DATABASE_URL = "postgres://localhost:5432/app"
✅ Environment-Based Config .env API_KEY=sk_live_abc123 DATABASE_URL=postgres://localhost:5432/app import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("API_KEY") DATABASE_URL = os.getenv("DATABASE_URL") if not API_KEY: raise RuntimeError("API_KEY not configured")
-
Now your code is:
- Deployable
- Secure
- Portable across environments
5️⃣ Structure Your Code Like a System, Not a Script
❌ Single File Chaos app.py
✅ Real Project Structure order_service/ │ ├── src/ │ └── order_service/ │ ├── __init__.py │ ├── api.py │ ├── services.py │ └── models.py │ ├── tests/ │ └── test_services.py │ ├── pyproject.toml └── README.md
-
This makes:
- Testing easier
- Imports clean
- Scaling possible
- Collaboration sane
- Structured logging
- Metrics
- Health checks
- Proper exit codes
- Other developers
- Unexpected input
- Bad networks
- Time
- Scale
6️⃣ If You’re Not Testing It, You’re Guessing
Production Test Example (pytest) test_services.py from order_service.services import calculate_total def test_calculate_total(): items = [10, 20, 30] assert calculate_total(items) == 60 Run pytest
Now your refactors won’t break production silently.
7️⃣ Type Hints Aren’t Decoration — They’re Contracts
❌ Untyped
def calculate_total(items): return sum(items)
✅ Typed
from typing import List def calculate_total(items: List[float]) -> float: return sum(items) Run static analysis: mypy .
Now your IDE catches mistakes before production does. 8️⃣ Production Is About Observability
-
At minimum:
Even something simple like
import sys def main(): try: run_app() except Exception as e: logger.exception("Application crashed") sys.exit(1) if __name__ == "__main__": main()
That exit code matters in Docker, CI/CD, and orchestration systems.
The Real Shift
The difference between a script and production code isn’t syntax.
It’s responsibility.
Scripts solve problems.
Production systems survive:
That shift changes how you write code forever.


If your Python app doesn’t have logging, validation, and monitoring…
ReplyDeleteIt’s not production.
It’s a demo with confidence.
Convince me otherwise.