Skip to main content

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/PropertyDescriptionExample
vars(namespace)Convert to dictionaryvars(args)
namespace.__dict__Direct access to internal dictargs.__dict__
hasattr(namespace, attr)Check if attribute existshasattr(args, 'verbose')
getattr(namespace, attr, default)Get attribute with defaultgetattr(args, 'count', 0)
setattr(namespace, attr, value)Set attribute valuesetattr(args, 'new_attr', 'value')
delattr(namespace, attr)Delete attributedelattr(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)
  • 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.