DEV Community

Cover image for Python 3.14 Unleashed: Template Strings & Modern Exception Handling (Part 1 - Chapter 2/3)
sizan mahmud0
sizan mahmud0

Posted on

Python 3.14 Unleashed: Template Strings & Modern Exception Handling (Part 1 - Chapter 2/3)

πŸ“š Series Navigation:

  • Chapter 1: Deferred Annotations & Multiple Interpreters β†’ [Read Chapter 1]
  • Chapter 2 (You are here): Template Strings & Exception Handling
  • Chapter 3: Control Flow in Finally Blocks & Key Takeaways β†’ [Read Chapter 3]

Welcome back! In Chapter 1, we explored deferred annotations and multiple interpreters. Now let's dive into two more game-changing features that will make your code more secure and readable.


3. PEP 750: Template Strings - Type-Safe String Formatting

What's New?

Template strings introduce a powerful and safe way to work with strings, especially for SQL queries, HTML templates, and shell commands, preventing injection attacks by design.

Basic Syntax

# Template strings with t"" prefix
from typing import Template

name = "Alice"
age = 30

# Simple template string
message = t"Hello, {name}! You are {age} years old."
print(message)

# Template strings preserve structure
user_input = "Robert'; DROP TABLE users;--"
query = t"SELECT * FROM users WHERE name = {user_input}"
# Python 3.14 automatically escapes dangerous inputs!
Enter fullscreen mode Exit fullscreen mode

Real-World Example: SQL Query Builder

from typing import Template
from datetime import date

class DatabaseQuery:
    """Type-safe SQL query builder using template strings"""

    @staticmethod
    def get_user_by_email(email: str) -> Template:
        # Automatic escaping prevents SQL injection
        return t"SELECT * FROM users WHERE email = {email}"

    @staticmethod
    def get_orders_by_date(user_id: int, start_date: date) -> Template:
        return t"""
            SELECT o.id, o.total, o.created_at
            FROM orders o
            WHERE o.user_id = {user_id}
            AND o.created_at >= {start_date}
            ORDER BY o.created_at DESC
        """

    @staticmethod
    def safe_search(search_term: str, category: str) -> Template:
        # Even malicious inputs are handled safely
        return t"""
            SELECT p.name, p.price, p.description
            FROM products p
            WHERE p.category = {category}
            AND p.name LIKE {search_term}
        """

# Usage
db = DatabaseQuery()

# Safe even with malicious input
malicious_input = "admin' OR '1'='1"
query = db.get_user_by_email(malicious_input)
# Result: SELECT * FROM users WHERE email = 'admin'' OR ''1''=''1'
# Properly escaped!

search_query = db.safe_search("%laptop%", "electronics")
print(search_query)
Enter fullscreen mode Exit fullscreen mode

Real-World Example: HTML Template Engine

from typing import Template
from html import escape

class HTMLBuilder:
    """Type-safe HTML generation"""

    @staticmethod
    def render_user_card(username: str, bio: str, posts_count: int) -> Template:
        # XSS protection built-in
        return t"""
            <div class="user-card">
                <h2>{username}</h2>
                <p>{bio}</p>
                <span class="badge">{posts_count} posts</span>
            </div>
        """

    @staticmethod
    def render_comment(author: str, content: str, timestamp: str) -> Template:
        return t"""
            <div class="comment">
                <strong>{author}</strong>
                <p>{content}</p>
                <time>{timestamp}</time>
            </div>
        """

# Usage
html_builder = HTMLBuilder()

# Even if user inputs malicious content, it's escaped
xss_attempt = "<script>alert('XSS')</script>"
card = html_builder.render_user_card(
    username="hacker",
    bio=xss_attempt,
    posts_count=42
)
# Output safely escapes the script tag!
print(card)
Enter fullscreen mode Exit fullscreen mode

Benefits for Clean Code

βœ… Automatic escaping prevents injection vulnerabilities

βœ… Type-safe interpolation catches errors at development time

βœ… Cleaner syntax than format strings or concatenation

βœ… Built-in security for web and database applications


4. PEP 758: Except and Except* Expressions Without Brackets - Cleaner Exception Handling

What's New?

Python 3.14 allows exception handling without brackets for single exception types, making code more readable and reducing visual noise.

Old Way vs New Way

# OLD WAY (Python 3.13 and earlier)
try:
    result = risky_operation()
except (ValueError):  # Unnecessary brackets for single exception
    handle_value_error()

# NEW WAY (Python 3.14)
try:
    result = risky_operation()
except ValueError:  # Clean and simple!
    handle_value_error()

# Still works for multiple exceptions
try:
    result = another_operation()
except ValueError, TypeError, KeyError:  # More readable!
    handle_multiple_errors()
Enter fullscreen mode Exit fullscreen mode

Exception Groups (except*)

# Python 3.14 simplifies exception group handling
try:
    async with asyncio.TaskGroup() as group:
        group.create_task(fetch_data_1())
        group.create_task(fetch_data_2())
        group.create_task(fetch_data_3())
except* ConnectionError:  # Clean syntax for exception groups
    print("Some connections failed")
except* TimeoutError:
    print("Some operations timed out")
except* ValueError:
    print("Some data was invalid")
Enter fullscreen mode Exit fullscreen mode

Real-World Example: API Error Handling

import httpx
from typing import Optional
import asyncio

class APIClient:
    """Clean exception handling for API requests"""

    async def fetch_user(self, user_id: int) -> Optional[dict]:
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(f"https://api.example.com/users/{user_id}")
                response.raise_for_status()
                return response.json()

        # Clean single exception handling
        except httpx.TimeoutError:
            print(f"Request timed out for user {user_id}")
            return None

        except httpx.NetworkError:
            print(f"Network error for user {user_id}")
            return None

        except httpx.HTTPStatusError:
            print(f"HTTP error for user {user_id}")
            return None

    async def fetch_multiple_users(self, user_ids: list[int]) -> list[dict]:
        """Fetch multiple users with exception group handling"""
        async with asyncio.TaskGroup() as group:
            tasks = [
                group.create_task(self.fetch_user(uid))
                for uid in user_ids
            ]

        # Handle exception groups cleanly
        try:
            results = [task.result() for task in tasks]
            return [r for r in results if r is not None]
        except* httpx.TimeoutError:
            print("Some requests timed out")
        except* httpx.NetworkError:
            print("Network issues encountered")

        return []

# Usage
async def main():
    client = APIClient()
    users = await client.fetch_multiple_users([1, 2, 3, 4, 5])
    print(f"Successfully fetched {len(users)} users")

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

Real-World Example: File Processing

from pathlib import Path
from typing import List
import json

class FileProcessor:
    """Clean exception handling for file operations"""

    def read_json_file(self, filepath: Path) -> dict:
        try:
            with open(filepath, 'r') as f:
                return json.load(f)

        except FileNotFoundError:
            print(f"File not found: {filepath}")
            return {}

        except json.JSONDecodeError:
            print(f"Invalid JSON in: {filepath}")
            return {}

        except PermissionError:
            print(f"Permission denied: {filepath}")
            return {}

    def process_multiple_files(self, filepaths: List[Path]) -> List[dict]:
        """Process multiple files with clean error handling"""
        results = []

        for filepath in filepaths:
            try:
                data = self.read_json_file(filepath)
                if data:
                    results.append(data)

            # Clean handling without brackets
            except OSError:
                print(f"OS error processing {filepath}")
                continue

            except Exception:
                print(f"Unexpected error with {filepath}")
                continue

        return results

# Usage
processor = FileProcessor()
files = [Path(f"data_{i}.json") for i in range(5)]
data = processor.process_multiple_files(files)
Enter fullscreen mode Exit fullscreen mode

Benefits for Clean Code

βœ… Reduced visual noise - no unnecessary brackets

βœ… More readable exception handling

βœ… Cleaner syntax for exception groups

βœ… Consistent style across codebases


πŸ”— Continue Reading

You're making great progress! Continue to Chapter 3 for the final feature and key takeaways.

πŸ‘‰ [Continue to Chapter 3 β†’]


πŸ“– Complete Series Navigation

Part 1 - Modern Features Guide:

  • Chapter 1: Deferred Annotations & Multiple Interpreters β†’ [Back to Chapter 1]
  • Chapter 2 (Current): Template Strings & Exception Handling
  • Chapter 3: Control Flow & Summary

Keywords: Python 3.14, template strings, exception handling, SQL injection prevention, XSS protection, PEP 750, PEP 758, Python security

Top comments (0)