Context in Python

Here’s the translation of the Go code to Python, with explanations in Markdown format suitable for Hugo:

Our example demonstrates the usage of context.Context for controlling cancellation in an HTTP server. A Context carries deadlines, cancellation signals, and other request-scoped values across API boundaries and threads.

import http.server
import socketserver
import time
import threading
from http import HTTPStatus

class CancellableHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/hello':
            self.hello()
        else:
            self.send_error(HTTPStatus.NOT_FOUND, "File not found")

    def hello(self):
        print("server: hello handler started")
        
        # Create an Event to simulate context cancellation
        cancel_event = threading.Event()
        
        # Start a timer to cancel after 2 seconds (simulating Ctrl+C)
        timer = threading.Timer(2, cancel_event.set)
        timer.start()

        try:
            # Simulate some work
            for _ in range(10):
                if cancel_event.is_set():
                    raise Exception("Operation cancelled")
                time.sleep(1)

            self.send_response(HTTPStatus.OK)
            self.end_headers()
            self.wfile.write(b"hello\n")
        except Exception as e:
            print(f"server: {str(e)}")
            self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
        finally:
            timer.cancel()
            print("server: hello handler ended")

def run_server():
    port = 8090
    handler = CancellableHandler
    with socketserver.TCPServer(("", port), handler) as httpd:
        print(f"Serving at port {port}")
        httpd.serve_forever()

if __name__ == "__main__":
    run_server()

In this Python version:

  1. We define a custom CancellableHandler that inherits from http.server.SimpleHTTPRequestHandler.

  2. The hello method simulates work that can be cancelled. It uses a threading.Event to simulate context cancellation.

  3. We start a timer that will set the cancel event after 2 seconds, simulating a cancellation signal (like Ctrl+C in the original example).

  4. The work simulation checks if the cancel event is set. If it is, it raises an exception.

  5. If the work completes without cancellation, it sends a “hello” response. If cancelled, it sends an internal server error.

  6. The run_server function sets up and starts the HTTP server.

To run the server:

$ python context_example.py

In another terminal, you can test the server:

$ curl localhost:8090/hello

You should see output in the server terminal similar to:

server: hello handler started
server: Operation cancelled
server: hello handler ended

This example demonstrates how you can implement cancellation in Python, which doesn’t have a direct equivalent to Go’s context.Context. Instead, we use threading.Event to simulate the cancellation mechanism.