python/cpython · error · AttributeError

module {__name__!r} has no attribute {name!r}

Error message

module {__name__!r} has no attribute {name!r}

What it means

Module-level __getattr__ in argparse handles attribute lookups that normal module content does not define. In current CPython it exists chiefly to serve argparse.__version__ with a PendingDeprecationWarning (removal scheduled for 3.20); any other unknown name raises AttributeError with this message. Code doing getattr(argparse, name) with a dynamic name hits this path constantly.

Source

Thrown at Lib/argparse.py:2976

        fmt = fmt.replace('error: %(message)s',
                        f'{theme.error}error:{theme.reset} {theme.message}%(message)s{theme.reset}')

        args = {'prog': self.prog, 'message': message}
        self.exit(2, fmt % args)

    def _warning(self, message):
        theme = self._get_theme(file=_sys.stderr)
        fmt = _('%(prog)s: warning: %(message)s\n')
        fmt = fmt.replace('warning: %(message)s',
                        f'{theme.warning}warning:{theme.reset} {theme.message}%(message)s{theme.reset}')
        args = {'prog': self.prog, 'message': message}
        self._print_message(fmt % args, _sys.stderr)

def __getattr__(name):
    if name == "__version__":
        warnings._deprecated("__version__", remove=(3, 20))
        return "1.1"  # Do not change
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Fix the attribute name (check dir(argparse)); e.g. ArgumentParser, ArgumentError, ArgumentTypeError, BooleanOptionalAction.
  2. Stop reading argparse.__version__; gate on hasattr(argparse, 'BooleanOptionalAction') or sys.version_info instead.
  3. For dynamic lookups always use getattr(argparse, name, default) so missing attributes yield your default, not AttributeError.

Example fix

# before
exc = argparse.ArgumentParsingError  # AttributeError
ver = argparse.__version__          # deprecated

# after
exc = argparse.ArgumentError
if hasattr(argparse, 'BooleanOptionalAction'):
    ...
Defensive patterns

Strategy: type-guard

Validate before calling

if not hasattr(argparse, 'BooleanOptionalAction'):
    raise RuntimeError('this tool requires Python 3.9+ argparse')

Type guard

def argparse_attr(name, default=None):
    """Safe attribute access on the argparse module."""
    return getattr(argparse, name, default)

# usage
exc = argparse_attr('ArgumentError', RuntimeError)

Try / catch

try:
    cls = getattr(argparse, name)
except AttributeError:
    raise RuntimeError(f'argparse on Python {sys.version_info[:2]} lacks {name}') from None

Prevention

When it happens

Trigger: argparse.__version__ (deprecated shim); getattr(argparse, opt, None) probing for option classes; typos like argparse.ArgumentParsingError (the real name is ArgumentError); hasattr-style feature detection against newer argparse APIs on older interpreters.

Common situations: Feature-detection helpers probing for classes added in newer Pythons (e.g. BooleanOptionalAction on 3.8); version-pinning code reading __version__; misspelled class names in plugins that build parsers dynamically.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/5bdc6d8b390f34e9. Report an issue: GitHub.