Week 8: Building Professional Python Applications
git - git add, git commit, git pushpip - pip install, pip list, pip freezedjango-admin - startproject, migrate, runserveraws - Manage cloud infrastructure from the terminaljupyter - jupyter notebook, jupyter labargparse is Pythonโs standard library for creating command-line interfaces--help documentation for freegit commit message.txtgit commit --amend -m "Fix bug"git add vs git commit"""simple_greeter.py - A friendly CLI greeter."""
import argparse
def main():
# Create the parser
parser = argparse.ArgumentParser(
description="A simple greeting tool",
epilog="Thanks for using the greeter!"
)
# Add positional argument (required)
parser.add_argument(
"name",
help="The name of the person to greet"
)
# Add optional flag
parser.add_argument(
"--loud",
action="store_true",
help="Greet in ALL CAPS"
)
# Parse the arguments
args = parser.parse_args()
# Use the arguments
greeting = f"Hello, {args.name}!"
if args.loud:
greeting = greeting.upper()
print(greeting)
if __name__ == "__main__":
main()"""api_fetcher.py - Fetch data from APIs with configurable options."""
import argparse
def fetch_data(api_name: str, resource: str, limit: int, output_file: str = None):
"""Fetch data from an API (implementation details omitted)."""
print(f"Fetching {limit} {resource} from {api_name}...")
if output_file:
print(f"Saving to {output_file}")
# Actual API call would go here
return {"status": "success", "count": limit}
def main():
parser = argparse.ArgumentParser(
description="Fetch data from various APIs"
)
# Positional arguments
parser.add_argument("api", help="API name (e.g., 'pokemon', 'jokes', 'weather')")
parser.add_argument("resource", help="Resource to fetch (e.g., 'pikachu', 'random')")
# Optional arguments with types
parser.add_argument(
"-l", "--limit",
type=int,
default=10,
help="Number of items to fetch (default: 10)"
)
parser.add_argument(
"-o", "--output",
help="Output file path (if not specified, prints to console)"
)
parser.add_argument(
"--format",
choices=["json", "csv", "txt"],
default="json",
help="Output format (default: json)"
)
args = parser.parse_args()
# Call the function with parsed arguments
result = fetch_data(args.api, args.resource, args.limit, args.output)
print(f"Result: {result}")
if __name__ == "__main__":
main()"""project_manager.py - Manage your project with subcommands."""
import argparse
def cmd_init(args):
"""Initialize a new project."""
print(f"Initializing project: {args.name}")
print(f"Template: {args.template}")
def cmd_build(args):
"""Build the project."""
print(f"Building project...")
if args.verbose:
print("Verbose output enabled")
def cmd_deploy(args):
"""Deploy the project."""
print(f"Deploying to {args.environment}")
def main():
parser = argparse.ArgumentParser(description="Project management tool")
subparsers = parser.add_subparsers(dest="command", help="Available commands")
# 'init' subcommand
init_parser = subparsers.add_parser("init", help="Initialize a new project")
init_parser.add_argument("name", help="Project name")
init_parser.add_argument("--template", default="basic", help="Project template")
init_parser.set_defaults(func=cmd_init)
# 'build' subcommand
build_parser = subparsers.add_parser("build", help="Build the project")
build_parser.add_argument("-v", "--verbose", action="store_true")
build_parser.set_defaults(func=cmd_build)
# 'deploy' subcommand
deploy_parser = subparsers.add_parser("deploy", help="Deploy the project")
deploy_parser.add_argument("environment", choices=["dev", "staging", "prod"])
deploy_parser.set_defaults(func=cmd_deploy)
args = parser.parse_args()
# Call the appropriate function
if hasattr(args, "func"):
args.func(args)
else:
parser.print_help()
if __name__ == "__main__":
main()rich or colorama for visual hierarchy--verbose or -v flag for debugging--version shows tool version"""my_api_tool.py - Professional CLI for your midterm API project."""
import argparse
import sys
from typing import Optional
def fetch_resource(resource_type: str, resource_id: Optional[str], limit: int):
"""Fetch data from your API."""
# Your API integration code here
print(f"Fetching {resource_type}...")
if resource_id:
print(f"ID: {resource_id}")
print(f"Limit: {limit}")
# Return the data
def main():
parser = argparse.ArgumentParser(
prog="my_api_tool",
description="Interact with [Your API Name] from the command line",
epilog="Example: python my_api_tool.py pokemon pikachu --format json"
)
parser.add_argument("resource", help="Resource type to fetch")
parser.add_argument("id", nargs="?", help="Optional resource ID")
parser.add_argument("-l", "--limit", type=int, default=10, help="Number of items")
parser.add_argument("--format", choices=["json", "pretty"], default="pretty")
parser.add_argument("-o", "--output", help="Save to file instead of printing")
try:
args = parser.parse_args()
result = fetch_resource(args.resource, args.id, args.limit)
print("Success!")
return 0 # Success exit code
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
return 1 # Error exit code
if __name__ == "__main__":
sys.exit(main()).py file - my_script.py does everythingutils.py, api.py, cli.py in one folder__init__.py filespip install your own code__init__.py file.py file__init__.py__init__.py: Marks directory as package, can contain initialization code__init__.py optional but still recommendedmy_api_project/
โ
โโโ my_api/ # Main package directory
โ โโโ __init__.py # Marks this as a package
โ โโโ api.py # API client code
โ โโโ cli.py # CLI interface
โ โโโ utils.py # Utility functions
โ
โโโ tests/ # Test directory
โ โโโ __init__.py
โ โโโ test_api.py
โ โโโ test_cli.py
โ
โโโ main.py # Entry point script
โโโ requirements.txt # Dependencies
โโโ README.md # Documentation
__init__.py file: Package initialization__init__.py (most common):# my_api/__init__.py
"""My API Client Package - A professional API wrapper."""
# Import key functions for convenient access
from my_api.api import fetch_data, APIClient
from my_api.utils import format_output
# Package metadata
__version__ = "1.0.0"
__author__ = "Your Name"
# Define public API - controls "from my_api import *"
__all__ = ["fetch_data", "APIClient", "format_output"]__name__ == "__main__" pattern__name__ is set to "__main__"__name__ is the module name# my_api/api.py
def fetch_data(api_name: str):
"""Fetch data from an API."""
print(f"Fetching from {api_name}")
return {"data": "example"}
def main():
"""Entry point for running as a script."""
result = fetch_data("pokemon")
print(result)
# Script mode: runs when file is executed directly
if __name__ == "__main__":
main()src/ structuremy_api_project/
โ
โโโ src/ # Source code (modern best practice)
โ โโโ my_api/
โ โโโ __init__.py
โ โโโ api.py
โ โโโ cli.py
โ โโโ utils.py
โ
โโโ tests/ # Tests outside source tree
โ โโโ __init__.py
โ โโโ test_api.py
โ โโโ test_cli.py
โ
โโโ docs/ # Documentation
โ โโโ index.md
โ
โโโ pyproject.toml # Modern Python project metadata
โโโ README.md
โโโ .gitignore
src/ layout?pyproject.tomlpyproject.toml:[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-api-tool"
version = "0.1.0"
description = "A professional API client for [Your API]"
authors = [{name = "Your Name", email = "you@example.com"}]
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"requests>=2.31.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"ruff>=0.1.0",
]
[project.scripts]
my-api = "my_api.cli:main" # Creates a 'my-api' commanduvuv is a blazingly fast Python package installer and resolver (written in Rust!)uv pip install works like pip install__init__.py files with proper importspyproject.toml configurationsmy_midterm_project/
โ
โโโ src/
โ โโโ my_api_tool/
โ โโโ __init__.py # Package initialization
โ โโโ api_client.py # API interaction logic
โ โโโ cli.py # argparse CLI interface
โ โโโ models.py # Data models/classes
โ โโโ utils.py # Helper functions
โ
โโโ tests/
โ โโโ __init__.py
โ โโโ test_api_client.py # API tests
โ โโโ test_cli.py # CLI tests
โ โโโ test_models.py # Model tests
โ
โโโ .github/
โ โโโ workflows/
โ โโโ tests.yml # GitHub Actions CI/CD
โ
โโโ pyproject.toml # Project configuration
โโโ README.md # Your documentation
โโโ .gitignore # Git exclusions
โโโ requirements.txt # Or use pyproject.toml dependencies
main.py or src/my_api_tool/__main__.py):src/my_api_tool/cli.py):"""Command-line interface for API tool."""
import argparse
import sys
from my_api_tool.api_client import APIClient
from my_api_tool.utils import format_output
def main():
parser = argparse.ArgumentParser(description="API client tool")
parser.add_argument("resource", help="Resource to fetch")
parser.add_argument("--format", choices=["json", "pretty"], default="pretty")
args = parser.parse_args()
try:
client = APIClient()
data = client.fetch(args.resource)
print(format_output(data, args.format))
return 0
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
return 1
if __name__ == "__main__":
sys.exit(main())__init__.py files by hand__name__ == "__main__" patternspip, venv, pyproject.toml)cargo new my_project creates perfect structuresrc/ layoutpyproject.toml for your CLI commandpip install -e . to install your project--help flag provides clear usage instructions__init__.py, proper imports, and logical modules__name__ == "__main__": Make code both runnable and importablepyproject.toml and uv represent the future of Python developmentLetโs build something professional! ๐
IS4010: App Development with AI