Technology Tales

Notes drawn from experiences in consumer and enterprise technology

11:40, 4th October 2026

There are several advanced Python techniques that can help developers write cleaner, more efficient code. These tricks leverage built-in features of the language and the standard library, offering solutions to common programming challenges without the need for external dependencies. Understanding and applying these techniques can significantly improve code quality and maintainability.

  • Replace while loops with sentinel values: Using iter(callable, sentinel) allows a loop to terminate automatically when a sentinel value is returned, eliminating the need for manual while True loops with break.

  • Manage multiple resources with ExitStack: ExitStack provides a way to handle a dynamic number of context managers, ensuring that all resources are thoroughly cleaned up in reverse order of their creation.

  • Slice binary data without copying: memoryview allows for efficient slicing of binary data without creating copies, which is especially useful when working with large buffers or packets.

  • Group concurrent failures with ExceptionGroup: Introduced in Python 3.11, ExceptionGroup allows multiple exceptions to be raised and handled together, making it easier to manage errors in concurrent or batch processing tasks.

  • Layer configuration dictionaries with ChainMap: ChainMap keeps configuration layers separate while allowing for ordered lookups, making it easier to manage and override settings without merging dictionaries.

  • Expose a read-only mapping with MappingProxyType: MappingProxyType provides a read-only view of a dictionary, preventing unintended modifications while still allowing for real-time updates to the underlying data.

  • Pre-fill positional slots with functools.Placeholder: Available in Python 3.14, functools.Placeholder allows developers to fix arguments in the middle of a function signature, making it easier to create flexible and reusable functions.

11:14, 19th September 2026

Making Python code run concurrently is straightforward, but making a bounded set of resources behave correctly under concurrency is a harder and more practical problem. Python 3.14 brought thread-safety improvements to asyncio and support for free-threaded builds, while 3.15 is set to add further structured concurrency features, making this a good moment to look at techniques that hold up under real production conditions.

The following methods were tested against a simulated dashboard aggregator that concurrently queries four backend services with different latency and capacity profiles.

  • Structured concurrency with TaskGroup: Unlike asyncio.gather, asyncio.TaskGroup guarantees that every task either completes or is cancelled before the block exits, and automatically cancels remaining tasks if one fails, preventing orphaned background tasks.
  • Bounding concurrency with Semaphore: A semaphore sized to each backend's real capacity, shared across the whole process rather than created per request, prevents overwhelming slower services. Testing showed a backend capped at three concurrent calls never exceeded that limit even under burst load.
  • Dynamic clean-up with AsyncExitStack: When the number of resources needed is only known at runtime, AsyncExitStack allows an arbitrary number of async context managers to be opened and guarantees they all close in reverse order, with no leaks regardless of how many are actually used.
  • Deadline propagation with asyncio.timeout(): Nested timeout scopes allow an inner deadline to catch a single slow backend without affecting others, while an outer deadline enforces a total time budget for the whole operation. Testing confirmed that partial results are returned cleanly even when some calls are cancelled mid-flight.
  • Live task introspection in Python 3.14: New commands, python -m asyncio ps and pstree, attach to a running process and display its live task tree without requiring code changes or advance logging, making it possible to diagnose hangs directly in production.

None of these techniques make code run faster. Instead, they make failure modes predictable, prevent one slow dependency from overwhelming a request and ensure resources are cleaned up correctly even when things go wrong. Together, they represent a fairly complete toolkit for building concurrency that remains reliable under real-world failure conditions.

11:07, 19th September 2026

A function can pass every test on the happy path and still fail in production: it might build its own network client, wait forever on a response, log a useless failure message, and have no way of testing what happens when the service goes down. None of these are style problems, so a linter would let them through. A handful of practices that make hidden assumptions visible makes the difference between code that survives production and code that does.

  • Passing dependencies in: rather than letting a function build its own client internally, accept it as a parameter, typed as a Protocol where possible. This lets tests substitute a fake collaborator instead of hitting the network or patching internals.
  • Letting context managers own clean-up: resources such as files, locks, transactions and temporary directories should be acquired and released within a with block, so clean-up still runs even when the code inside raises an exception.
  • Giving external waits a deadline: unbounded waits are an undeclared failure mode. Every network, database or queue call should have a timeout, paired with a deliberate decision about what happens when it expires, whether that is a retry, a fallback or a loud failure.
  • Logging with investigable context: a message like "processing failed" tells you little. Including structured fields such as job IDs lets whoever is on call trace the line back to the actual problem, without ever logging sensitive data.
  • Testing the failure contract: passing tests on friendly inputs say little about how code behaves under pressure. Parametrised tests covering missing, malformed or delayed inputs, and assertions on observable behaviour rather than internal call sequences, make the other practices enforceable.
  • Treating package metadata as a contract: pyproject.toml should declare build requirements, supported Python versions and dependencies, so assumptions about the runtime environment are visible rather than guessed at. Declaring a dependency range is not the same as locking exact versions.
  • Deprecating before deleting: public functions being phased out should raise a DeprecationWarning naming the replacement, with the migration documented and surfaced deliberately, since these warnings are hidden by default outside __main__.

These seven habits share a common thread: each takes an assumption that would otherwise sit only in a developer's head and puts it somewhere visible, whether that is a type signature, a test, a log line or a configuration file. Code that shows its assumptions is easier for another developer, a test suite or an operator to maintain.

10:59, 19th September 2026

Python functions sometimes handle several tasks at once: a single block might calculate prices, mutate shared state and simulate side effects all in the same place. Separating those responsibilities into distinct functions is one approach, applying a few consistent habits to isolate each task.

  • Note where a function's name does not match everything it does, where a variable shifts meaning partway through, or where a calculation depends on the order in which statements run rather than on a finished value.
  • Split responsibilities into small functions: each piece takes plain inputs and returns a plain output, which also tends to reduce ordering issues since calculations work on finished values rather than a running total.
  • Replace loose dictionaries with data classes: giving orders and their items a defined structure makes the available fields and types explicit and lets a linter flag mismatches before the code runs.
  • Raise exceptions instead of printing warnings: a missing value stops execution immediately rather than being logged and passed over, which can make issues easier to identify during testing and debugging.
  • Test each function independently: once logic is separated, a failing test points to the affected piece rather than leaving several responsibilities to consider as possible causes.

Applying these steps one function at a time, rather than rewriting a whole file in one go, keeps changes reviewable and the code working throughout. The underlying pattern (list what a function does, extract each responsibility, model data properly, raise exceptions on failure and test in isolation) applies to any function handling more than one task.

14:35, 12th September 2026

A Python library called FireDucks has been developed to significantly improve the performance of data processing tasks typically handled by pandas. It achieves this through the use of lazy execution, compiler optimisations and multithreaded processing, which allow it to execute operations more efficiently, particularly on large datasets. In benchmark tests involving seven common data-processing workloads, FireDucks demonstrated speed increases ranging from 2.66x to 20.77x compared to pandas, with the most significant improvement observed in sorting operations. The library is designed to be compatible with pandas, enabling users to leverage familiar syntax while benefiting from enhanced performance. Although it is not a complete replacement for pandas, FireDucks offers a viable alternative for tasks where performance gains are critical, especially when working with large-scale data.

14:29, 21st August 2026

For efficient processing of large datasets, row-by-row loops in pandas should generally be replaced with column-based methods that use compiled operations. Vectorised arithmetic handles calculations, apply() supports custom conditional logic, np.where() manages binary conditions and np.select() handles multiple outcomes, while map() performs dictionary lookups, the .str accessor processes string columns and groupby() with agg() produces grouped summaries. Choosing the method that matches the transformation makes code faster, clearer and easier to maintain.

14:25, 21st August 2026

Efficient data preparation in Python can be improved through three idiomatic Pandas patterns: method chaining with .assign(), .query() and .pipe() for clearer, safer workflows; converting repetitive string columns to categorical data and using vectorised string operations to reduce memory use and processing time; and applying groupby().transform() to fill missing values with group-specific statistics while preserving row alignment. Together, these approaches reduce unnecessary copying, avoid SettingWithCopyWarning and replace slow row-by-row or custom grouping operations with scalable vectorised processing.

14:19, 21st August 2026

Data cleaning, a time-consuming yet essential part of data work, can be streamlined with five Python libraries that address common challenges such as structural inconsistencies, text encoding errors and data validation. Pyjanitor offers a fluent, chainable API for cleaning and transforming DataFrames, while Great Expectations enforces data quality through defined expectations and generates validation reports. Ftfy repairs Unicode and encoding issues in text, ydata-profiling automates exploratory data analysis with interactive reports and Cerberus validates arbitrary data structures with schema rules. Together, these tools enhance efficiency by reducing boilerplate code, improving data integrity and providing insights into dataset quality, allowing professionals to focus on analysis rather than manual corrections.

11:15, 21st August 2026

NumPy performance can be improved by replacing explicit Python loops and np.vectorize with native universal functions and broadcasting, which perform calculations in compiled code without unnecessary data duplication. In-place operators and the out parameter reduce temporary array creation, lowering memory use and improving speed. Basic slicing creates efficient, zero-copy views, whereas advanced indexing creates full copies; views are faster but share memory with the original array, so changes to them may affect the underlying data.

15:32, 6th June 2026

FastAPI is a popular Python framework for building modern APIs, valued for its speed, clean syntax and developer-friendly design. It scales from simple back-ends to machine learning applications, making it a practical choice across a wide range of projects.

A range of GitHub repositories can help developers learn the framework in different ways. These cover curated ecosystem resources, full-stack project templates combining FastAPI with React, PostgreSQL and Docker, practical coding tips for writing cleaner applications, and small stand-alone examples suited to beginners. Further repositories address user authentication and management, step-by-step project-based learning, reusable project templates for more scalable builds, microservices architecture using Docker Compose and Nginx and the use of FastAPI in AI image generation and machine learning model serving.

FastAPI Cloud offers a managed deployment platform that takes a locally built application live through a command-line interface with minimal configuration. Features include interactive API documentation, log monitoring and integrations comparable to other modern managed hosting platforms.

  • The content, images, and materials on this website are protected by copyright law and may not be reproduced, distributed, transmitted, displayed, or published in any form without the prior written permission of the copyright holder. All trademarks, logos, and brand names mentioned on this website are the property of their respective owners. Unauthorised use or duplication of these materials may violate copyright, trademark and other applicable laws, and could result in criminal or civil penalties.

  • All comments on this website are moderated and should contribute meaningfully to the discussion. We welcome diverse viewpoints expressed respectfully, but reserve the right to remove any comments containing hate speech, profanity, personal attacks, spam, promotional content or other inappropriate material without notice. Please note that comment moderation may take up to 24 hours, and that repeatedly violating these guidelines may result in being banned from future participation.

  • By submitting a comment, you grant us the right to publish and edit it as needed, whilst retaining your ownership of the content. Your email address will never be published or shared, though it is required for moderation purposes.