Practical Example: ConnectionFailedError Definition

๐Ÿท๏ธ Error Handling and Exceptions / Custom Exceptions


๐ŸŒ Context Introduction

When building tools that interact with external servicesโ€”like databases, APIs, or remote serversโ€”connection failures are a common reality. Instead of relying on generic Python exceptions, creating a custom exception like ConnectionFailedError makes your code more readable and your debugging more precise. This example shows how to define and use a custom exception for network-related failures.


โš™๏ธ What Is a Custom Exception?

A custom exception is a new exception class you define by inheriting from Python's built-in Exception class. It allows you to:

  • Give meaningful names to specific error conditions.
  • Add extra attributes (like the hostname or port) to carry context.
  • Catch and handle errors more selectively in your code.

๐Ÿ› ๏ธ Defining ConnectionFailedError

To define a custom exception, you create a class that inherits from Exception. You can optionally add an init method to store additional information.

Example structure:

  • Class name: ConnectionFailedError
  • Inherits from: Exception
  • Attributes: host (the target server address) and port (the target port number)

How to define it:

  • Start with class ConnectionFailedError(Exception):
  • Inside the class, define def init(self, host, port, message="Connection failed"):
  • Call super().init(message) to initialize the base exception.
  • Store self.host = host and self.port = port.

๐Ÿ“Š Comparison: Built-in Exception vs. Custom Exception

Feature Built-in Exception (e.g., ConnectionError) Custom ConnectionFailedError
Name clarity Generic, could mean anything Specific to connection failures
Extra context No host or port info Stores host and port details
Catch precision Catches all connection issues Catches only your defined scenario
Readability Requires comments to explain Self-documenting by name

๐Ÿ•ต๏ธ How to Raise and Catch ConnectionFailedError

Raising the exception:

  • Use raise ConnectionFailedError(host="api.example.com", port=443) inside your code when a connection attempt fails.
  • You can pass a custom message like raise ConnectionFailedError(host, port, "Timeout after 5 seconds").

Catching the exception:

  • Use try: and except ConnectionFailedError as e: to handle only this specific error.
  • Inside the except block, access e.host, e.port, and str(e) to get details.

Example flow:

  • Try to connect to a server.
  • If connection fails, raise ConnectionFailedError with the host and port.
  • In the calling code, catch ConnectionFailedError and log the host and port for debugging.

๐Ÿงฉ Why This Matters for Engineers

  • Debugging speed: When you see ConnectionFailedError, you immediately know it's a network issue, not a logic bug.
  • Error propagation: You can add context (like hostname) that helps trace the failure back to its source.
  • Code maintainability: Other engineers reading your code understand exactly what failed without digging into implementation details.
  • Separation of concerns: Network-related errors are handled separately from other exception types.

โœ… Best Practices for Custom Exceptions

  • Keep the exception name descriptive and specific to the failure type.
  • Include only relevant attributes that help diagnose the issue.
  • Always call super().init() to ensure the base exception works correctly.
  • Document your custom exception in the class docstring so others know when to raise and catch it.
  • Avoid overusing custom exceptionsโ€”use them only when a built-in exception doesn't capture the needed context.

๐Ÿ“ Final Thought

Defining a ConnectionFailedError is a simple but powerful way to make your error handling more expressive. It turns a vague failure into a clear, actionable signal. As you build more complex systems, custom exceptions become an essential tool for writing robust, debuggable code.


A ConnectionFailedError is a custom exception class that engineers define to handle network connection failures in a clear and specific way.

๐ŸŸข Example 1: Basic ConnectionFailedError class definition

This example shows the simplest way to define a custom exception by inheriting from Python's built-in Exception class.

class ConnectionFailedError(Exception):
    pass

๐Ÿ“ค Output: No output (class definition only)


๐ŸŸก Example 2: Raising a ConnectionFailedError

This example demonstrates how to raise the custom exception when a connection attempt fails.

class ConnectionFailedError(Exception):
    pass

def connect_to_server(address):
    raise ConnectionFailedError(f"Cannot connect to {address}")

connect_to_server("192.168.1.100")

๐Ÿ“ค Output: Traceback (most recent call last): ... ConnectionFailedError: Cannot connect to 192.168.1.100


๐Ÿ”ต Example 3: Catching a ConnectionFailedError with try-except

This example shows how engineers can catch and handle the custom exception gracefully.

class ConnectionFailedError(Exception):
    pass

def connect_to_server(address):
    raise ConnectionFailedError(f"Cannot connect to {address}")

try:
    connect_to_server("192.168.1.100")
except ConnectionFailedError as error:
    print(f"Connection issue: {error}")

๐Ÿ“ค Output: Connection issue: Cannot connect to 192.168.1.100


๐ŸŸฃ Example 4: ConnectionFailedError with custom attributes

This example adds a status code attribute to give engineers more information about the failure.

class ConnectionFailedError(Exception):
    def __init__(self, address, status_code):
        self.address = address
        self.status_code = status_code
        message = f"Failed to connect to {address} (status: {status_code})"
        super().__init__(message)

def check_server(address):
    status = 503
    raise ConnectionFailedError(address, status)

try:
    check_server("api.example.com")
except ConnectionFailedError as error:
    print(f"Error: {error}")
    print(f"Server: {error.address}, Status: {error.status_code}")

๐Ÿ“ค Output: Error: Failed to connect to api.example.com (status: 503)
Server: api.example.com, Status: 503


๐Ÿ”ด Example 5: Practical retry logic with ConnectionFailedError

This example shows how engineers can implement a retry mechanism when a connection fails.

import time

class ConnectionFailedError(Exception):
    pass

def attempt_connection(server_name):
    import random
    if random.randint(1, 3) == 1:
        print(f"Connected to {server_name}")
        return True
    else:
        raise ConnectionFailedError(f"Could not reach {server_name}")

def connect_with_retry(server_name, max_retries=3):
    for attempt in range(1, max_retries + 1):
        try:
            return attempt_connection(server_name)
        except ConnectionFailedError as error:
            print(f"Attempt {attempt} failed: {error}")
            if attempt < max_retries:
                time.sleep(1)
    print("All connection attempts failed")
    return False

connect_with_retry("database.internal")

๐Ÿ“ค Output: Attempt 1 failed: Could not reach database.internal
Attempt 2 failed: Could not reach database.internal
Connected to database.internal


Comparison Table

Feature Built-in Exception Custom ConnectionFailedError
Specificity Generic error Clear connection failure intent
Readability Vague message Self-documenting class name
Catch precision Catches all errors Catches only connection issues
Custom attributes Not supported Can add address, status code, etc.
Debugging value Low High for network engineers

๐ŸŒ Context Introduction

When building tools that interact with external servicesโ€”like databases, APIs, or remote serversโ€”connection failures are a common reality. Instead of relying on generic Python exceptions, creating a custom exception like ConnectionFailedError makes your code more readable and your debugging more precise. This example shows how to define and use a custom exception for network-related failures.


โš™๏ธ What Is a Custom Exception?

A custom exception is a new exception class you define by inheriting from Python's built-in Exception class. It allows you to:

  • Give meaningful names to specific error conditions.
  • Add extra attributes (like the hostname or port) to carry context.
  • Catch and handle errors more selectively in your code.

๐Ÿ› ๏ธ Defining ConnectionFailedError

To define a custom exception, you create a class that inherits from Exception. You can optionally add an init method to store additional information.

Example structure:

  • Class name: ConnectionFailedError
  • Inherits from: Exception
  • Attributes: host (the target server address) and port (the target port number)

How to define it:

  • Start with class ConnectionFailedError(Exception):
  • Inside the class, define def init(self, host, port, message="Connection failed"):
  • Call super().init(message) to initialize the base exception.
  • Store self.host = host and self.port = port.

๐Ÿ“Š Comparison: Built-in Exception vs. Custom Exception

Feature Built-in Exception (e.g., ConnectionError) Custom ConnectionFailedError
Name clarity Generic, could mean anything Specific to connection failures
Extra context No host or port info Stores host and port details
Catch precision Catches all connection issues Catches only your defined scenario
Readability Requires comments to explain Self-documenting by name

๐Ÿ•ต๏ธ How to Raise and Catch ConnectionFailedError

Raising the exception:

  • Use raise ConnectionFailedError(host="api.example.com", port=443) inside your code when a connection attempt fails.
  • You can pass a custom message like raise ConnectionFailedError(host, port, "Timeout after 5 seconds").

Catching the exception:

  • Use try: and except ConnectionFailedError as e: to handle only this specific error.
  • Inside the except block, access e.host, e.port, and str(e) to get details.

Example flow:

  • Try to connect to a server.
  • If connection fails, raise ConnectionFailedError with the host and port.
  • In the calling code, catch ConnectionFailedError and log the host and port for debugging.

๐Ÿงฉ Why This Matters for Engineers

  • Debugging speed: When you see ConnectionFailedError, you immediately know it's a network issue, not a logic bug.
  • Error propagation: You can add context (like hostname) that helps trace the failure back to its source.
  • Code maintainability: Other engineers reading your code understand exactly what failed without digging into implementation details.
  • Separation of concerns: Network-related errors are handled separately from other exception types.

โœ… Best Practices for Custom Exceptions

  • Keep the exception name descriptive and specific to the failure type.
  • Include only relevant attributes that help diagnose the issue.
  • Always call super().init() to ensure the base exception works correctly.
  • Document your custom exception in the class docstring so others know when to raise and catch it.
  • Avoid overusing custom exceptionsโ€”use them only when a built-in exception doesn't capture the needed context.

๐Ÿ“ Final Thought

Defining a ConnectionFailedError is a simple but powerful way to make your error handling more expressive. It turns a vague failure into a clear, actionable signal. As you build more complex systems, custom exceptions become an essential tool for writing robust, debuggable code.

Interactive Views

You are currently in ๐Ÿ“š All-in-One mode. Use the tabs at the top to switch to ๐Ÿ“– Theory Only or ๐Ÿ’ป Code Only views.

A ConnectionFailedError is a custom exception class that engineers define to handle network connection failures in a clear and specific way.

๐ŸŸข Example 1: Basic ConnectionFailedError class definition

This example shows the simplest way to define a custom exception by inheriting from Python's built-in Exception class.

class ConnectionFailedError(Exception):
    pass

๐Ÿ“ค Output: No output (class definition only)


๐ŸŸก Example 2: Raising a ConnectionFailedError

This example demonstrates how to raise the custom exception when a connection attempt fails.

class ConnectionFailedError(Exception):
    pass

def connect_to_server(address):
    raise ConnectionFailedError(f"Cannot connect to {address}")

connect_to_server("192.168.1.100")

๐Ÿ“ค Output: Traceback (most recent call last): ... ConnectionFailedError: Cannot connect to 192.168.1.100


๐Ÿ”ต Example 3: Catching a ConnectionFailedError with try-except

This example shows how engineers can catch and handle the custom exception gracefully.

class ConnectionFailedError(Exception):
    pass

def connect_to_server(address):
    raise ConnectionFailedError(f"Cannot connect to {address}")

try:
    connect_to_server("192.168.1.100")
except ConnectionFailedError as error:
    print(f"Connection issue: {error}")

๐Ÿ“ค Output: Connection issue: Cannot connect to 192.168.1.100


๐ŸŸฃ Example 4: ConnectionFailedError with custom attributes

This example adds a status code attribute to give engineers more information about the failure.

class ConnectionFailedError(Exception):
    def __init__(self, address, status_code):
        self.address = address
        self.status_code = status_code
        message = f"Failed to connect to {address} (status: {status_code})"
        super().__init__(message)

def check_server(address):
    status = 503
    raise ConnectionFailedError(address, status)

try:
    check_server("api.example.com")
except ConnectionFailedError as error:
    print(f"Error: {error}")
    print(f"Server: {error.address}, Status: {error.status_code}")

๐Ÿ“ค Output: Error: Failed to connect to api.example.com (status: 503)
Server: api.example.com, Status: 503


๐Ÿ”ด Example 5: Practical retry logic with ConnectionFailedError

This example shows how engineers can implement a retry mechanism when a connection fails.

import time

class ConnectionFailedError(Exception):
    pass

def attempt_connection(server_name):
    import random
    if random.randint(1, 3) == 1:
        print(f"Connected to {server_name}")
        return True
    else:
        raise ConnectionFailedError(f"Could not reach {server_name}")

def connect_with_retry(server_name, max_retries=3):
    for attempt in range(1, max_retries + 1):
        try:
            return attempt_connection(server_name)
        except ConnectionFailedError as error:
            print(f"Attempt {attempt} failed: {error}")
            if attempt < max_retries:
                time.sleep(1)
    print("All connection attempts failed")
    return False

connect_with_retry("database.internal")

๐Ÿ“ค Output: Attempt 1 failed: Could not reach database.internal
Attempt 2 failed: Could not reach database.internal
Connected to database.internal


Comparison Table

Feature Built-in Exception Custom ConnectionFailedError
Specificity Generic error Clear connection failure intent
Readability Vague message Self-documenting class name
Catch precision Catches all errors Catches only connection issues
Custom attributes Not supported Can add address, status code, etc.
Debugging value Low High for network engineers