Code Examples: Turning Python Scripts Into Production Systems

In my previous article, From Script to Production: What Python Tutorials Don’t Teach , I explained the mindset shift required to move beyond beginner-level Python.

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
  • 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:
    • Structured logging
    • Metrics
    • Health checks
    • Proper exit codes

    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:

    • Other developers
    • Unexpected input
    • Bad networks
    • Time
    • Scale

    That shift changes how you write code forever.

Comments

  1. If your Python app doesn’t have logging, validation, and monitoring…

    It’s not production.

    It’s a demo with confidence.

    Convince me otherwise.

    ReplyDelete

Post a Comment

Popular posts from this blog

Introducing Mega-Net HospitalPro

Nigerians and Programming Languages

Mega-Net HospitalPro version 8.0