argparse.Namespace
The Namespace class is a simple container object that holds the parsed command-line arguments. It's returned by ArgumentParser.parse_args() and provides attribute-based access to argument values.
Basic Usage
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--name', default='World')
parser.add_argument('--count', type=int, default=1)
parser.add_argument('--verbose', action='store_true')
# Parse arguments into a Namespace object
args = parser.parse_args(['--name', 'Alice', '--count', '3', '--verbose'])
# Access arguments as attributes
print(f"Name: {args.name}") # Name: Alice
print(f"Count: {args.count}") # Count: 3
print(f"Verbose: {args.verbose}") # Verbose: True
# Namespace object representation
print(args) # Namespace(name='Alice', count=3, verbose=True)
Namespace Class Reference
Class Signature
class Namespace(**kwargs)
Constructor
Creates a new Namespace object with optional initial values.
# Empty namespace
ns = argparse.Namespace()
# Pre-populated namespace
ns = argparse.Namespace(name='Alice', age=30, active=True)
print(ns.name) # Alice
print(ns.age) # 30
Core Operations
Attribute Access
Namespace objects support both attribute and dictionary-style access patterns.
# Attribute access (standard)
print(args.filename)
print(args.verbose)
# Check if attribute exists
if hasattr(args, 'output'):
print(f"Output file: {args.output}")
# Get with default value
output_file = getattr(args, 'output', 'default.txt')
Attribute Assignment
You can modify Namespace objects after creation.
# Set new attributes
args.processed_count = 0
args.start_time = time.time()
# Modify existing attributes
args.verbose = not args.verbose
args.count += 1
Dictionary Conversion
Convert Namespace to dictionary for easier manipulation.
# Convert to dictionary
arg_dict = vars(args)
print(arg_dict) # {'name': 'Alice', 'count': 3, 'verbose': True}
# Create namespace from dictionary
new_args = argparse.Namespace(**arg_dict)
# Merge with additional values
combined = argparse.Namespace(**arg_dict, extra_param='value')
Namespace Methods and Properties
| Method/Property | Description | Example |
|---|---|---|
vars(namespace) | Convert to dictionary | vars(args) |
namespace.__dict__ | Direct access to internal dict | args.__dict__ |
hasattr(namespace, attr) | Check if attribute exists | hasattr(args, 'verbose') |
getattr(namespace, attr, default) | Get attribute with default | getattr(args, 'count', 0) |
setattr(namespace, attr, value) | Set attribute value | setattr(args, 'new_attr', 'value') |
delattr(namespace, attr) | Delete attribute | delattr(args, 'unwanted') |
Common Usage Patterns
1. Namespace as Configuration Object
def process_files(config):
"""Process files using configuration from Namespace."""
if config.verbose:
print(f"Processing {len(config.files)} files")
for filename in config.files:
if config.backup:
backup_file(filename)
process_file(filename, config.output_format)
# Use parsed arguments as configuration
parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='+')
parser.add_argument('--verbose', action='store_true')
parser.add_argument('--backup', action='store_true')
parser.add_argument('--output-format', default='json')
args = parser.parse_args()
process_files(args) # Pass namespace directly
2. Merging Multiple Sources
# Default configuration
defaults = argparse.Namespace(
debug=False,
port=8080,
host='localhost'
)
# Command-line arguments
parser = argparse.ArgumentParser()
parser.add_argument('--debug', action='store_true')
parser.add_argument('--port', type=int)
parser.add_argument('--host')
args = parser.parse_args()
# Merge: command-line overrides defaults
config = argparse.Namespace(**vars(defaults))
for key, value in vars(args).items():
if value is not None: # Only override if specified
setattr(config, key, value)
3. Namespace Validation
def validate_config(args):
"""Validate parsed arguments and add computed values."""
# Ensure required combinations
if args.output_file and not args.input_file:
raise ValueError("Output file requires input file")
# Add computed attributes
args.output_dir = os.path.dirname(args.output_file or 'output')
args.timestamp = datetime.now().isoformat()
# Normalize paths
if args.input_file:
args.input_file = os.path.abspath(args.input_file)
return args
# Use validation
args = parser.parse_args()
args = validate_config(args)
4. Namespace Inheritance for Subcommands
# Base configuration for all subcommands
base_parser = argparse.ArgumentParser(add_help=False)
base_parser.add_argument('--verbose', action='store_true')
base_parser.add_argument('--config-file')
# Main parser with subcommands
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='command')
# Subcommands inherit base configuration
create_parser = subparsers.add_parser('create', parents=[base_parser])
create_parser.add_argument('name')
delete_parser = subparsers.add_parser('delete', parents=[base_parser])
delete_parser.add_argument('name')
# All subcommands have access to --verbose and --config-file
5. Converting Namespace to Typed Objects
from dataclasses import dataclass
@dataclass
class Config:
input_file: str
output_file: str = 'output.txt'
verbose: bool = False
count: int = 1
def namespace_to_config(args):
"""Convert Namespace to typed configuration object."""
return Config(**{
key: value for key, value in vars(args).items()
if key in Config.__annotations__
})
# Convert parsed args to typed config
args = parser.parse_args()
config = namespace_to_config(args)
Namespace Inspection and Debugging
Display All Arguments
def show_config(args, title="Configuration"):
"""Pretty-print namespace contents."""
print(f"\n{title}:")
print("-" * len(title))
for key, value in sorted(vars(args).items()):
print(f" {key:20} = {value!r}")
print()
# Usage
args = parser.parse_args()
show_config(args)
Filter and Group Arguments
def categorize_args(args):
"""Categorize arguments by purpose."""
input_args = {}
output_args = {}
control_args = {}
for key, value in vars(args).items():
if 'input' in key or key in ['file', 'source']:
input_args[key] = value
elif 'output' in key or key in ['dest', 'target']:
output_args[key] = value
else:
control_args[key] = value
return input_args, output_args, control_args
Argument Difference Analysis
def compare_namespaces(ns1, ns2):
"""Compare two namespaces and show differences."""
all_keys = set(vars(ns1).keys()) | set(vars(ns2).keys())
for key in sorted(all_keys):
val1 = getattr(ns1, key, '<missing>')
val2 = getattr(ns2, key, '<missing>')
if val1 != val2:
print(f"{key}: {val1!r} -> {val2!r}")
Common Patterns and Best Practices
1. Immutable Namespace (Read-Only Configuration)
class ReadOnlyNamespace(argparse.Namespace):
"""Namespace that prevents modification after initialization."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._frozen = True
def __setattr__(self, name, value):
if hasattr(self, '_frozen') and self._frozen:
raise AttributeError(f"Cannot modify read-only namespace: {name}")
super().__setattr__(name, value)
# Use with parser
parser = argparse.ArgumentParser()
# ... add arguments ...
args = parser.parse_args(namespace=ReadOnlyNamespace())
2. Namespace with Default Values
class DefaultNamespace(argparse.Namespace):
"""Namespace that returns default values for missing attributes."""
def __init__(self, defaults=None, **kwargs):
super().__init__(**kwargs)
self._defaults = defaults or {}
def __getattr__(self, name):
if name in self._defaults:
return self._defaults[name]
raise AttributeError(f"'{type(self).__name__}' has no attribute '{name}'")
# Usage
defaults = {'timeout': 30, 'retries': 3}
args = parser.parse_args(namespace=DefaultNamespace(defaults))
print(args.timeout) # 30 (from defaults)
3. Nested Namespace for Complex Configuration
def create_nested_namespace(args):
"""Convert flat namespace to nested structure."""
nested = argparse.Namespace()
# Group related arguments
nested.database = argparse.Namespace(
host=args.db_host,
port=args.db_port,
name=args.db_name
)
nested.logging = argparse.Namespace(
level=args.log_level,
file=args.log_file,
format=args.log_format
)
# Keep other args at top level
nested.verbose = args.verbose
nested.debug = args.debug
return nested
Integration Examples
Working with Configuration Files
import json
def load_config_file(config_file):
"""Load configuration from JSON file into Namespace."""
with open(config_file) as f:
config_data = json.load(f)
return argparse.Namespace(**config_data)
def save_config_file(args, config_file):
"""Save Namespace to JSON configuration file."""
with open(config_file, 'w') as f:
json.dump(vars(args), f, indent=2)
# Usage
if args.config_file:
file_config = load_config_file(args.config_file)
# Merge file config with command-line args
for key, value in vars(file_config).items():
if not hasattr(args, key) or getattr(args, key) is None:
setattr(args, key, value)
Environment Variable Integration
import os
def apply_env_defaults(args, env_prefix='MYAPP_'):
"""Apply environment variables as defaults."""
for key in vars(args):
env_key = f"{env_prefix}{key.upper()}"
if env_key in os.environ and getattr(args, key) is None:
env_value = os.environ[env_key]
# Type conversion based on existing value type
if hasattr(args, key):
current_type = type(getattr(args, key))
if current_type == bool:
env_value = env_value.lower() in ('true', '1', 'yes')
elif current_type == int:
env_value = int(env_value)
elif current_type == float:
env_value = float(env_value)
setattr(args, key, env_value)
Related Documentation
- ArgumentParser - Creates Namespace objects
- Action Classes - How arguments populate Namespace
- Argparse Tutorial - Working with parsed arguments
See Also
- types.SimpleNamespace - Similar container for arbitrary attributes
- dataclasses - Structured alternative for configuration objects
- configparser - Configuration file parsing
Namespace objects provide a simple, flexible way to work with parsed command-line arguments. Understanding their behavior is essential for building robust command-line applications.