or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dependency-tracking.mdindex.mdlazy-imports.mdsetuptools-integration.md

lazy-imports.mddocs/

0

# Lazy Import Handling

1

2

Import Tracker provides sophisticated lazy import error handling that defers `ModuleNotFoundError` exceptions until the missing module is actually used. This enables graceful handling of optional dependencies and prevents crashes during import of packages with complex hierarchical wild imports.

3

4

## Capabilities

5

6

### Lazy Import Error Context Manager

7

8

Enables lazy import errors either globally or within a specific context. When enabled, import failures are deferred until the module is actually accessed.

9

10

```python { .api }

11

def lazy_import_errors(

12

*,

13

get_extras_modules: Optional[Callable[[], Set[str]]] = None,

14

make_error_message: Optional[Callable[[str], str]] = None,

15

):

16

"""

17

Enable lazy import errors that defer ModuleNotFoundError until module usage.

18

19

Parameters:

20

- get_extras_modules: Optional[Callable[[], Set[str]]] - Function returning set of extras module names

21

- make_error_message: Optional[Callable[[str], str]] - Custom error message generator function

22

23

Returns:

24

Context manager object that can be used with 'with' statement or called directly

25

26

Note: get_extras_modules and make_error_message are mutually exclusive

27

"""

28

```

29

30

**Usage Examples:**

31

32

```python

33

import import_tracker

34

35

# Global lazy import errors

36

import_tracker.lazy_import_errors()

37

import some_optional_package # Won't crash if missing

38

39

# Context manager approach

40

with import_tracker.lazy_import_errors():

41

import optional_module

42

import another_optional_module

43

44

# Access triggers the error

45

try:

46

optional_module.some_function() # ModuleNotFoundError raised here

47

except ModuleNotFoundError as e:

48

print(f"Optional dependency missing: {e}")

49

50

# Custom error messages for extras

51

def get_my_extras():

52

return {"mylib.viz", "mylib.ml", "mylib.web"}

53

54

with import_tracker.lazy_import_errors(get_extras_modules=get_my_extras):

55

import mylib.viz # Error includes pip install command if missing

56

```

57

58

### Custom Error Messages

59

60

Customize error messages for missing modules, particularly useful for indicating which extras need to be installed:

61

62

```python

63

# Using get_extras_modules for automatic pip install messages

64

def get_extras_modules():

65

return {"mypackage.plotting", "mypackage.database"}

66

67

import_tracker.lazy_import_errors(get_extras_modules=get_extras_modules)

68

69

# When mypackage.plotting is missing, error message will be:

70

# "No module named 'matplotlib'. To install the missing dependencies,

71

# run `pip install mypackage[mypackage.plotting]`"

72

73

# Custom error message function

74

def custom_error_message(missing_module):

75

return f"Module {missing_module} is not available. Install it with: pip install {missing_module}"

76

77

import_tracker.lazy_import_errors(make_error_message=custom_error_message)

78

```

79

80

### Lazy Module Wrapper

81

82

Provides a module wrapper that defers the actual import until an attribute is accessed, useful for expensive imports.

83

84

```python { .api }

85

class LazyModule(ModuleType):

86

"""

87

A module subclass that wraps another module with lazy importing.

88

89

The wrapped module is not imported until an attribute is accessed.

90

"""

91

92

def __init__(self, name: str, package: Optional[str] = None):

93

"""

94

Initialize lazy module wrapper.

95

96

Parameters:

97

- name: str - Name of module to import lazily

98

- package: Optional[str] - Parent package name for relative imports

99

"""

100

101

def __getattr__(self, name: str) -> any:

102

"""

103

Trigger lazy import when attribute is accessed.

104

105

Parameters:

106

- name: str - Attribute name being accessed

107

108

Returns:

109

Attribute from the lazily imported module

110

"""

111

```

112

113

**Usage Example:**

114

115

```python

116

import import_tracker

117

118

# Create lazy module - no import happens yet

119

numpy = import_tracker.LazyModule("numpy")

120

pandas = import_tracker.LazyModule("pandas")

121

122

# Import only happens when attribute is accessed

123

array = numpy.array([1, 2, 3]) # numpy imported here

124

df = pandas.DataFrame({"x": [1, 2, 3]}) # pandas imported here

125

126

# Relative import with package

127

submodule = import_tracker.LazyModule(".utils", package="mypackage")

128

result = submodule.helper_function() # mypackage.utils imported here

129

```

130

131

## Advanced Usage Patterns

132

133

### Selective Lazy Imports

134

135

Apply lazy import handling only to specific modules while requiring others to exist:

136

137

```python

138

import import_tracker

139

140

# Core dependencies must exist

141

from mylib import core, utils

142

143

# Optional dependencies can be missing

144

with import_tracker.lazy_import_errors():

145

from mylib import plotting, advanced_analytics

146

147

# Use with error handling

148

def create_plot(data):

149

try:

150

return plotting.make_chart(data)

151

except ModuleNotFoundError:

152

return "Plotting not available - install with: pip install mylib[plotting]"

153

```

154

155

### Hierarchical Wild Imports

156

157

Handle complex packages that use wild imports across many submodules:

158

159

```python

160

import import_tracker

161

162

# Enable lazy errors before importing large package

163

import_tracker.lazy_import_errors()

164

165

# This won't crash even if some submodules have missing dependencies

166

from large_scientific_package import *

167

168

# Errors only occur when specific functionality is used

169

try:

170

result = some_advanced_function()

171

except ModuleNotFoundError as e:

172

print(f"Advanced features not available: {e}")

173

```

174

175

### Integration with Package Extras

176

177

Coordinate lazy imports with setuptools extras for better user experience:

178

179

```python

180

import import_tracker

181

182

def get_my_extras():

183

"""Return set of modules managed as extras."""

184

return {

185

"mypackage.visualization",

186

"mypackage.machine_learning",

187

"mypackage.database"

188

}

189

190

# Enable with extras integration

191

import_tracker.lazy_import_errors(get_extras_modules=get_my_extras)

192

193

# Imports that might fail get helpful error messages

194

try:

195

from mypackage.visualization import plot_data

196

plot_data(my_data)

197

except ModuleNotFoundError as e:

198

# Error includes: "run `pip install mypackage[mypackage.visualization]`"

199

print(e)

200

```

201

202

## Implementation Notes

203

204

- Lazy import errors work by installing custom meta path finders that intercept import failures

205

- The system tracks the calling package to avoid interfering with unrelated imports

206

- When used as a context manager, the lazy error handlers are automatically cleaned up on exit

207

- The `LazyModule` class extends `ModuleType` and delegates all attribute access to the actual module once imported

208

- Import stack tracking is disabled in lazy import mode to avoid performance overhead