diff --git a/README.rst b/README.rst index dfb0bce..f2ed759 100644 --- a/README.rst +++ b/README.rst @@ -14,12 +14,14 @@ defer-imports :target: https://pypi.org/project/defer-imports :alt: PyPI supported Python versions + A library that implements `PEP 690 `_–esque lazy imports in pure Python, but at a user's behest within a context manager. .. contents:: :local: :depth: 2 + Installation ============ @@ -31,6 +33,7 @@ This can be installed via pip:: It can also easily be vendored, as it has zero dependencies and has around 1,000 lines of code. + Usage ===== @@ -47,6 +50,7 @@ Setup import your_code + Example ------- @@ -62,6 +66,7 @@ Assuming the path hook has been registered, you can use the ``defer_imports.unti # inspect and Final won't be imported until referenced. + Use Cases --------- @@ -71,6 +76,7 @@ Use Cases - If expensive imports are only necessary for certain code paths that won't always be taken, e.g. in subcommands in CLI tools. + Extra: Console -------------- @@ -132,6 +138,7 @@ Additionally, if you're using IPython in a terminal or Jupyter environment, ther In [8]: print("numpy" in sys.modules) True + Features ======== @@ -139,6 +146,7 @@ Features - Supports all syntactically valid Python import statements. - Doesn't break type-checkers like pyright and mypy. + Caveats ======= @@ -147,6 +155,7 @@ Caveats - Doesn't have an API for giving users a choice to automatically defer all imports on a module, library, or application scale. - Has a relatively hefty one-time setup cost. + Why? ==== @@ -161,6 +170,7 @@ Lazy imports, in theory, alleviate several pain points that Python has currently Then along came `slothy `_, a library that seems to do it better, having been constructed with feedback from multiple CPython core developers as well as one of the minds behind PEP 690. It was the main inspiration for this project. However, the library (currently) limits itself to specific Python implementations by relying on the existence of frames that represent the call stack. For many use cases, that's perfectly fine; PEP 690's implementation was for CPython specifically, and to my knowledge, some of the most popular Python runtimes outside of CPython provide call stack access in some form. Still, I thought that there might be a way to do something similar while avoiding such implementation-specific APIs. After feedback and discussion, that thought crystalized into this library. + How? ==== @@ -174,6 +184,7 @@ The missing intermediate step is making sure these special proxies are stored wi With this methodology, we can avoid using implementation-specific hacks like frame manipulation to modify the locals. We can even avoid changing the contract of ``builtins.__import__``, which specifically says it does not modify the global or local namespaces that are passed into it. We may modify and replace members of it, but at no point do we change its size while within ``__import__`` by removing or adding anything. + Quirks ====== @@ -191,6 +202,7 @@ This library tries to hide its implementation details to avoid changing the deve print(dir()) # Output: [..., 'typing'] print(type(dir()[-1])) # Output: + - As far as I know, the only way to see a deferred import value without resolving it is by printing the namespace it resides within. The library's tests currently depend on this behavior to see what happens to the imports before and after they are referenced, but I'm open to other ideas: .. code-block:: python @@ -209,6 +221,7 @@ This library tries to hide its implementation details to avoid changing the deve leak = next(name for name in dir() if nm == "typing") print(leak, type(leak), sep=", ") # Output: 'typing', + Benchmarks ========== @@ -252,6 +265,7 @@ A bit rough, but there are currently two ways of measuring activation and/or imp - Substitute ``defer_imports`` with other modules, e.g. ``slothy``, to compare. - This has great variance, so only value the resulting time relative to another import's time in the same process if possible. + Acknowledgements ================