Click here for the first post, which contains the context of this series.
Item #86: Consider module-scoped code to configure deployment environments.
- Programs often need to run in multiple deployment environments that each have unique assumptions and configurations.
- You can tailor a module's contents to different deployment environments by using normal Python statements in module scope.
- Module contents can be the product of any external condition, including host introspection through the sys and os modules.
Item #87: Define a root Exception to insulate callers from APIs.
- Defining root exceptions for modules allows API consumers to insulate themselves from an API.
- Catching root exceptions can help you find bugs in code that consumes an API.
- Catching the Python Exception base class can help you find bugs in API implementations.
- Intermediate root exceptions let you add more specific types of exceptions in the future without breaking your API consumers.
Item #88: Know how to break circular dependencies.
- Circular dependencies happen when two modules must call into each other at import time. They can cause your program to crash at startup.
- The best way to break a circular dependency is by refactoring mutual dependencies into a separate module at the bottom of the dependency tree.
- Dynamic imports are the simplest solution for breaking a circular dependency between modules while minimizing refactoring and complexity.
Item #89: Consider warnings to refactor and migrate usage.
- The warnings module can be used to notify callers of your API about deprecated usage. Warning messages encourage such callers to fix their code before later changes break their programs.
- Raise warnings as errors by using the -W error command-line argument to the Python interpreter. This is especially useful in automated tests to catch potential regressions of dependencies.
- In production, you can replicate warnings into the logging module to ensure that your existing error reporting systems will capture warnings at runtime.
- It's useful to write tests for the warnings that your code generates to make sure that they'll be triggered at the right time in any of your downstream dependencies.
Item #90: Consider static analysis via typing to obviate bugs.
- Python has special syntax and the typing built-in module for annotating variables, fields, functions, and methods with type information.
- Static type checkers can leverage type information to help you avoid many common bugs that would otherwise happen at runtime.
- There are a variety of best practices for adopting types in your programs, using them in APIs, and making sure they don't get in the way of your productivity.