{"record":{"id":"5bdc6d8b390f34e9","repo":"python/cpython","slug":"module-name-r-has-no-attribute-name-r","errorCode":null,"errorMessage":"module {__name__!r} has no attribute {name!r}","messagePattern":"module (.+?) has no attribute (.+?)","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"Lib/argparse.py","lineNumber":2976,"sourceCode":"        fmt = fmt.replace('error: %(message)s',\n                        f'{theme.error}error:{theme.reset} {theme.message}%(message)s{theme.reset}')\n\n        args = {'prog': self.prog, 'message': message}\n        self.exit(2, fmt % args)\n\n    def _warning(self, message):\n        theme = self._get_theme(file=_sys.stderr)\n        fmt = _('%(prog)s: warning: %(message)s\\n')\n        fmt = fmt.replace('warning: %(message)s',\n                        f'{theme.warning}warning:{theme.reset} {theme.message}%(message)s{theme.reset}')\n        args = {'prog': self.prog, 'message': message}\n        self._print_message(fmt % args, _sys.stderr)\n\ndef __getattr__(name):\n    if name == \"__version__\":\n        warnings._deprecated(\"__version__\", remove=(3, 20))\n        return \"1.1\"  # Do not change\n    raise AttributeError(f\"module {__name__!r} has no attribute {name!r}\")\n","sourceCodeStart":2958,"sourceCodeEnd":2977,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/argparse.py#L2958-L2977","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the attribute name (check dir(argparse)); e.g. ArgumentParser, ArgumentError, ArgumentTypeError, BooleanOptionalAction.","Stop reading argparse.__version__; gate on hasattr(argparse, 'BooleanOptionalAction') or sys.version_info instead.","For dynamic lookups always use getattr(argparse, name, default) so missing attributes yield your default, not AttributeError."],"exampleFix":"# before\nexc = argparse.ArgumentParsingError  # AttributeError\nver = argparse.__version__          # deprecated\n\n# after\nexc = argparse.ArgumentError\nif hasattr(argparse, 'BooleanOptionalAction'):\n    ...","handlingStrategy":"type-guard","validationCode":"if not hasattr(argparse, 'BooleanOptionalAction'):\n    raise RuntimeError('this tool requires Python 3.9+ argparse')","typeGuard":"def argparse_attr(name, default=None):\n    \"\"\"Safe attribute access on the argparse module.\"\"\"\n    return getattr(argparse, name, default)\n\n# usage\nexc = argparse_attr('ArgumentError', RuntimeError)","tryCatchPattern":"try:\n    cls = getattr(argparse, name)\nexcept AttributeError:\n    raise RuntimeError(f'argparse on Python {sys.version_info[:2]} lacks {name}') from None","preventionTips":["Never read argparse.__version__; gate features with hasattr or sys.version_info.","Use getattr(argparse, name, default) for every dynamic module lookup.","Spell-check class names against dir(argparse) when wiring plugins dynamically."],"tags":["argparse","attributeerror","getattr","deprecation"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}