0
# Namespace Management
1
2
Enhanced namespace objects and configuration management utilities that provide nested structure support, dictionary-like access patterns, serialization capabilities, and configuration manipulation tools. The Namespace class extends argparse.Namespace with advanced features for handling complex, hierarchical configurations.
3
4
## Capabilities
5
6
### Namespace Class
7
8
Extended namespace class that supports nested configuration structures with dictionary-like access patterns and comprehensive manipulation methods.
9
10
```python { .api }
11
class Namespace:
12
def __init__(self, *args, **kwargs):
13
"""
14
Create a new namespace object.
15
16
Args:
17
*args: Positional arguments (dicts or namespaces to merge)
18
**kwargs: Keyword arguments to set as attributes
19
"""
20
21
def __getitem__(self, key: str) -> Any:
22
"""
23
Get item using dictionary-style access with dot notation support.
24
25
Args:
26
key: Key to retrieve (supports dot notation like 'a.b.c')
27
28
Returns:
29
Any: Value at the specified key
30
31
Raises:
32
KeyError: If key is not found
33
"""
34
35
def __setitem__(self, key: str, value: Any) -> None:
36
"""
37
Set item using dictionary-style access with dot notation support.
38
39
Args:
40
key: Key to set (supports dot notation like 'a.b.c')
41
value: Value to set
42
"""
43
44
def __delitem__(self, key: str) -> None:
45
"""
46
Delete item using dictionary-style access.
47
48
Args:
49
key: Key to delete (supports dot notation)
50
51
Raises:
52
KeyError: If key is not found
53
"""
54
55
def __contains__(self, key: str) -> bool:
56
"""
57
Check if key exists in namespace.
58
59
Args:
60
key: Key to check (supports dot notation)
61
62
Returns:
63
bool: True if key exists
64
"""
65
66
def as_dict(self) -> Dict[str, Any]:
67
"""
68
Convert namespace to nested dictionary.
69
70
Returns:
71
Dict[str, Any]: Dictionary representation of namespace
72
"""
73
74
def as_flat(self) -> argparse.Namespace:
75
"""
76
Convert to flat argparse.Namespace with dot-separated keys.
77
78
Returns:
79
argparse.Namespace: Flattened namespace
80
"""
81
82
def items(self, branches: bool = False) -> Iterator[Tuple[str, Any]]:
83
"""
84
Iterate over namespace items.
85
86
Args:
87
branches: Whether to include intermediate branch nodes
88
89
Yields:
90
Tuple[str, Any]: Key-value pairs
91
"""
92
93
def keys(self, branches: bool = False) -> Iterator[str]:
94
"""
95
Iterate over namespace keys.
96
97
Args:
98
branches: Whether to include intermediate branch keys
99
100
Yields:
101
str: Namespace keys
102
"""
103
104
def values(self, branches: bool = False) -> Iterator[Any]:
105
"""
106
Iterate over namespace values.
107
108
Args:
109
branches: Whether to include intermediate branch values
110
111
Yields:
112
Any: Namespace values
113
"""
114
115
def get_sorted_keys(self, branches: bool = True) -> List[str]:
116
"""
117
Get sorted list of all keys in namespace.
118
119
Args:
120
branches: Whether to include intermediate branch keys
121
122
Returns:
123
List[str]: Sorted list of keys
124
"""
125
126
def clone(self) -> "Namespace":
127
"""
128
Create a deep copy of the namespace.
129
130
Returns:
131
Namespace: Deep copy of this namespace
132
"""
133
134
def update(self, value: Union["Namespace", Any], key: Optional[str] = None) -> "Namespace":
135
"""
136
Update namespace with values from another namespace or dict.
137
138
Args:
139
value: Values to merge (Namespace, dict, or other object)
140
key: Optional key to update specific nested location
141
142
Returns:
143
Namespace: Updated namespace (self)
144
"""
145
146
def get(self, key: str, default: Any = None) -> Any:
147
"""
148
Get value with default fallback.
149
150
Args:
151
key: Key to retrieve (supports dot notation)
152
default: Default value if key not found
153
154
Returns:
155
Any: Value at key or default
156
"""
157
158
def pop(self, key: str, default: Any = None) -> Any:
159
"""
160
Remove and return value at key.
161
162
Args:
163
key: Key to remove (supports dot notation)
164
default: Default value if key not found
165
166
Returns:
167
Any: Removed value or default
168
"""
169
```
170
171
### Namespace Utilities
172
173
Utility functions for converting between namespaces and dictionaries, and for cleaning configuration objects.
174
175
```python { .api }
176
def dict_to_namespace(obj: Dict[str, Any]) -> Namespace:
177
"""
178
Convert nested dictionary to nested namespace.
179
180
Args:
181
obj: Dictionary to convert
182
183
Returns:
184
Namespace: Converted namespace object
185
"""
186
187
def strip_meta(cfg: Union[Namespace, Dict]) -> Union[Namespace, Dict]:
188
"""
189
Remove all metadata keys from configuration object.
190
191
Args:
192
cfg: Configuration object (Namespace or dict)
193
194
Returns:
195
Union[Namespace, Dict]: Configuration with metadata removed
196
"""
197
```
198
199
## Usage Examples
200
201
### Basic Namespace Operations
202
203
```python
204
from jsonargparse import Namespace
205
206
# Create namespace
207
config = Namespace()
208
209
# Set values using attribute access
210
config.model_name = "resnet50"
211
config.epochs = 100
212
213
# Set nested values using dot notation
214
config["training.learning_rate"] = 0.001
215
config["training.batch_size"] = 32
216
config["data.train_path"] = "/data/train"
217
config["data.val_path"] = "/data/val"
218
219
# Access values multiple ways
220
print(config.model_name) # Attribute access
221
print(config["epochs"]) # Dictionary access
222
print(config["training.learning_rate"]) # Dot notation
223
224
# Check if keys exist
225
if "training.learning_rate" in config:
226
print("Learning rate is set")
227
228
# Convert to dictionary
229
config_dict = config.as_dict()
230
print(config_dict)
231
# {
232
# "model_name": "resnet50",
233
# "epochs": 100,
234
# "training": {"learning_rate": 0.001, "batch_size": 32},
235
# "data": {"train_path": "/data/train", "val_path": "/data/val"}
236
# }
237
```
238
239
### Nested Configuration Management
240
241
```python
242
from jsonargparse import Namespace
243
244
# Create nested configuration
245
config = Namespace({
246
"model": {
247
"type": "cnn",
248
"layers": 5,
249
"activation": "relu"
250
},
251
"training": {
252
"optimizer": "adam",
253
"learning_rate": 0.001,
254
"epochs": 100
255
},
256
"data": {
257
"batch_size": 32,
258
"shuffle": True
259
}
260
})
261
262
# Access nested values
263
print(f"Model type: {config.model.type}")
264
print(f"Learning rate: {config['training.learning_rate']}")
265
266
# Update nested values
267
config.model.layers = 10
268
config["training.epochs"] = 200
269
270
# Add new nested section
271
config["logging.level"] = "INFO"
272
config["logging.file"] = "training.log"
273
274
print(config.logging.level) # INFO
275
print(config.logging.file) # training.log
276
```
277
278
### Configuration Merging and Updates
279
280
```python
281
from jsonargparse import Namespace
282
283
# Base configuration
284
base_config = Namespace({
285
"model": {"type": "resnet", "layers": 18},
286
"training": {"epochs": 100, "learning_rate": 0.001},
287
"data": {"batch_size": 32}
288
})
289
290
# User overrides
291
user_config = Namespace({
292
"model": {"layers": 50}, # Override layers
293
"training": {"epochs": 200}, # Override epochs
294
"evaluation": {"metrics": ["accuracy", "f1"]} # Add new section
295
})
296
297
# Merge configurations
298
base_config.update(user_config)
299
300
print(base_config.as_dict())
301
# {
302
# "model": {"type": "resnet", "layers": 50},
303
# "training": {"epochs": 200, "learning_rate": 0.001},
304
# "data": {"batch_size": 32},
305
# "evaluation": {"metrics": ["accuracy", "f1"]}
306
# }
307
```
308
309
### Namespace Iteration
310
311
```python
312
from jsonargparse import Namespace
313
314
config = Namespace({
315
"model": {"type": "cnn", "layers": 5},
316
"training": {"epochs": 100, "lr": 0.001},
317
"debug": True
318
})
319
320
# Iterate over all key-value pairs (leaf nodes only)
321
print("All configuration values:")
322
for key, value in config.items():
323
print(f" {key}: {value}")
324
# Output:
325
# model.type: cnn
326
# model.layers: 5
327
# training.epochs: 100
328
# training.lr: 0.001
329
# debug: True
330
331
# Iterate including branch nodes
332
print("\nAll keys including branches:")
333
for key in config.keys(branches=True):
334
print(f" {key}")
335
# Output:
336
# model
337
# model.type
338
# model.layers
339
# training
340
# training.epochs
341
# training.lr
342
# debug
343
344
# Get sorted keys
345
sorted_keys = config.get_sorted_keys(branches=False)
346
print(f"\nSorted leaf keys: {sorted_keys}")
347
```
348
349
### Dictionary Conversion
350
351
```python
352
from jsonargparse import Namespace, dict_to_namespace
353
354
# Convert dict to namespace
355
config_dict = {
356
"database": {
357
"host": "localhost",
358
"port": 5432,
359
"credentials": {
360
"username": "user",
361
"password": "pass"
362
}
363
},
364
"cache": {
365
"enabled": True,
366
"ttl": 3600
367
}
368
}
369
370
config = dict_to_namespace(config_dict)
371
372
# Access with dot notation
373
print(config.database.host) # localhost
374
print(config["database.credentials.username"]) # user
375
print(config.cache.enabled) # True
376
377
# Convert back to dict
378
result_dict = config.as_dict()
379
print(result_dict == config_dict) # True
380
```
381
382
### Namespace Cloning and Manipulation
383
384
```python
385
from jsonargparse import Namespace
386
387
# Original configuration
388
original = Namespace({
389
"model": {"type": "resnet", "layers": 18},
390
"training": {"epochs": 100}
391
})
392
393
# Create independent copy
394
copy = original.clone()
395
396
# Modify copy without affecting original
397
copy.model.layers = 50
398
copy.training.epochs = 200
399
copy["new_section.value"] = "added"
400
401
print(f"Original layers: {original.model.layers}") # 18
402
print(f"Copy layers: {copy.model.layers}") # 50
403
404
# Use get() with defaults
405
batch_size = original.get("training.batch_size", 32)
406
print(f"Batch size: {batch_size}") # 32 (default)
407
408
# Pop values
409
epochs = copy.pop("training.epochs", 100)
410
print(f"Popped epochs: {epochs}") # 200
411
print(f"Epochs after pop: {copy.get('training.epochs', 'missing')}") # missing
412
```
413
414
### Configuration Cleaning
415
416
```python
417
from jsonargparse import Namespace, strip_meta
418
419
# Configuration with metadata
420
config = Namespace({
421
"model": {"type": "cnn", "layers": 5},
422
"training": {"epochs": 100},
423
"__metadata__": {"version": "1.0", "created": "2023-01-01"},
424
"_internal_config": {"debug": True}
425
})
426
427
# Remove metadata keys
428
clean_config = strip_meta(config)
429
430
print("Original keys:", list(config.keys(branches=True)))
431
print("Clean keys:", list(clean_config.keys(branches=True)))
432
433
# Metadata keys starting with _ or __ are removed
434
```
435
436
### Flat Namespace Conversion
437
438
```python
439
from jsonargparse import Namespace
440
441
# Nested namespace
442
nested = Namespace({
443
"model": {"type": "cnn", "layers": 5},
444
"training": {"epochs": 100, "lr": 0.001}
445
})
446
447
# Convert to flat namespace with dot-separated keys
448
flat = nested.as_flat()
449
450
print(f"model.type: {flat.model.type}") # AttributeError - no nesting
451
print(f"model.type: {getattr(flat, 'model.type')}") # cnn
452
print(f"training.epochs: {getattr(flat, 'training.epochs')}") # 100
453
454
# Useful for integrating with systems expecting flat namespaces
455
```
456
457
### Advanced Namespace Usage
458
459
```python
460
from jsonargparse import Namespace
461
462
# Complex nested configuration
463
config = Namespace()
464
465
# Build configuration programmatically
466
config["experiments.exp1.model.type"] = "resnet"
467
config["experiments.exp1.model.layers"] = 18
468
config["experiments.exp1.training.epochs"] = 100
469
470
config["experiments.exp2.model.type"] = "densenet"
471
config["experiments.exp2.model.layers"] = 121
472
config["experiments.exp2.training.epochs"] = 150
473
474
# Access experiments
475
for exp_name in ["exp1", "exp2"]:
476
exp_config = config[f"experiments.{exp_name}"]
477
print(f"{exp_name}: {exp_config.model.type}-{exp_config.model.layers}")
478
print(f" Epochs: {exp_config.training.epochs}")
479
480
# Delete entire experiment
481
del config["experiments.exp1"]
482
483
print("Remaining experiments:", list(config.experiments.keys()))
484
```