{"id":6489,"library":"zope-deferredimport","title":"Zope Deferred Import","description":"zope.deferredimport allows you to perform imports of names that will only be resolved when used in the code. This utility library helps improve application startup time and manage potential circular dependencies by making imports lazy. The current version is 6.1.1, and it receives updates as part of the broader Zope Foundation ecosystem.","status":"active","version":"6.1.1","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/zope.deferredimport","tags":["zope","import","lazy-loading","performance","startup-time","utility"],"install":[{"cmd":"pip install zope.deferredimport","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"symbol":"deferredImport","correct":"from zope.deferredimport import deferredImport"}],"quickstart":{"code":"import sys\nfrom zope.deferredimport import deferredImport\n\n# Simulate a module that would be slow to import or cause a circular dependency\n# In a real scenario, 'my_app.utils' might be a separate file/module.\nsys.modules['my_app.utils'] = type('module', (object,), {\n    'complex_function': lambda: \"Complex function executed!\",\n    'helper_constant': 42,\n    'another_item': 'hello'\n})\n\n# Define deferred imports for a target module 'my_app.api'\ndeferredImport(\n    'my_app.api',\n    'my_app.utils:complex_function',\n    'my_app.utils:helper_constant',\n    'my_app.utils:non_existent_item', # This will raise AttributeError on access\n)\n\n# At this point, 'my_app.api' exists but its contents are not loaded (lazy)\nprint(f\"Is 'my_app.api' in sys.modules? {'my_app.api' in sys.modules}\")\nprint(f\"Has 'complex_function' been imported yet? {'complex_function' in sys.modules.get('my_app.api', {}).__dict__}\")\n\n# Accessing 'complex_function' triggers its import from 'my_app.utils'\nimport my_app.api\nprint(f\"Value of complex_function: {my_app.api.complex_function()}\")\nprint(f\"Has 'complex_function' been imported now? {'complex_function' in sys.modules.get('my_app.api', {}).__dict__}\")\nprint(f\"Value of helper_constant: {my_app.api.helper_constant}\")\n\n# Accessing a non-existent item will raise an AttributeError as expected\ntry:\n    my_app.api.non_existent_item\nexcept AttributeError as e:\n    print(f\"Expected error for non-existent item: {e}\")\n\n# Clean up sys.modules for example isolation (not typically done in app code)\ndel sys.modules['my_app.utils']\ndel sys.modules['my_app.api']","lang":"python","description":"This quickstart demonstrates how to use `deferredImport` to lazily load symbols into a target module. The symbols are only imported from their source module when they are first accessed, helping to reduce initial load times. It also shows how attempts to access non-existent deferred items will correctly raise an `AttributeError`."},"warnings":[{"fix":"Upgrade Python to 3.10+ or pin `zope.deferredimport<6` in your project's dependencies.","message":"Versions 6.x and above of `zope.deferredimport` require Python 3.10 or higher. Projects on older Python versions (e.g., 3.9 or earlier) must use an older version of the library (e.g., 5.x) or upgrade their Python interpreter.","severity":"breaking","affected_versions":"6.0.0+"},{"fix":"Thoroughly test deferred imports. During debugging, inspect `sys.modules` and the target module's `__dict__` to verify that the source modules are correctly loaded and contain the expected symbols.","message":"When a deferred-imported symbol is accessed but its underlying source cannot be found (e.g., the module doesn't exist, or the attribute is missing), the `AttributeError` will be raised at the *point of access*, not necessarily where `deferredImport` was called. This can make debugging unexpected `AttributeError`s tricky as the traceback doesn't immediately point to the source of the deferred definition.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure that code paths requiring deferred symbols are genuinely lazy. Defer imports only for components that are not always needed during application startup or during module initialization.","message":"The performance benefits (faster startup time) of `zope.deferredimport` only materialize if the deferred symbols are *not* immediately accessed after the `deferredImport` call. If a symbol is accessed on the next line, the import happens immediately, largely negating the startup improvement for that specific symbol.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If `from ... import *` behavior is desired, explicitly define or append the names of the deferred symbols to the `__all__` list in the module where `deferredImport` is used.","message":"Modules using `deferredImport` do not automatically populate their `__all__` attribute with the deferred symbols. This means that `from my_module import *` will not expose deferred names without explicit modification of `my_module.__all__`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z"}