diff --git a/Lib/configparser.py b/Lib/configparser.py index a53ac87276445ad..e8c370c2cbf25cc 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -1373,14 +1373,25 @@ class ConverterMapping(MutableMapping): GETTERCRE = re.compile(r"^get(?P.+)$") + # The set of ``get`` converter methods is fixed per parser class, so + # cache the discovered names per class instead of running dir() + a regex + # over every attribute on each ConfigParser construction. + _getter_names_cache = {} + def __init__(self, parser): self._parser = parser - self._data = {} - for getter in dir(self._parser): - m = self.GETTERCRE.match(getter) - if not m or not callable(getattr(self._parser, getter)): - continue - self._data[m.group('name')] = None # See class docstring. + cls = type(parser) + try: + names = ConverterMapping._getter_names_cache[cls] + except KeyError: + getter_re = self.GETTERCRE + names = tuple( + m['name'] + for getter in dir(parser) + if (m := getter_re.match(getter)) and callable(getattr(parser, getter)) + ) + ConverterMapping._getter_names_cache[cls] = names + self._data = dict.fromkeys(names) # See class docstring (values None). def __getitem__(self, key): return self._data[key] diff --git a/Misc/NEWS.d/next/Library/2026-06-02-15-44-59.gh-issue-150819.D3JQey.rst b/Misc/NEWS.d/next/Library/2026-06-02-15-44-59.gh-issue-150819.D3JQey.rst new file mode 100644 index 000000000000000..acdab6daa338277 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-02-15-44-59.gh-issue-150819.D3JQey.rst @@ -0,0 +1,3 @@ +Speed up :class:`configparser.ConfigParser` construction by caching the +discovered ``get*`` converter method names per parser class. Patch by Bernát +Gábor.