[Python-checkins] r88318 - python/branches/release27-maint/Lib/ConfigParser.py

raymond.hettinger python-checkins at python.org
Wed Feb 2 09:37:11 CET 2011


Author: raymond.hettinger
Date: Wed Feb  2 09:37:11 2011
New Revision: 88318

Log:
Issue 11089:  Fix performance bug in ConfigParser that impaired its
usability for large config files.

The ConfigParser.get() method should have been O(1) but had
O(n) dict copies and updates on every call.  This was 
exacerbated by using OrderedDicts which do not copy or 
update nearly as fast as regular dicts which are coded in C.



Modified:
   python/branches/release27-maint/Lib/ConfigParser.py

Modified: python/branches/release27-maint/Lib/ConfigParser.py
==============================================================================
--- python/branches/release27-maint/Lib/ConfigParser.py	(original)
+++ python/branches/release27-maint/Lib/ConfigParser.py	Wed Feb  2 09:37:11 2011
@@ -545,6 +545,38 @@
                 if isinstance(val, list):
                     options[name] = '\n'.join(val)
 
+import UserDict as _UserDict
+
+class _Chainmap(_UserDict.DictMixin):
+    """Combine multiple mappings for successive lookups.
+
+    For example, to emulate Python's normal lookup sequence:
+
+        import __builtin__
+        pylookup = _Chainmap(locals(), globals(), vars(__builtin__))
+    """
+
+    def __init__(self, *maps):
+        self._maps = maps
+
+    def __getitem__(self, key):
+        for mapping in self._maps:
+            try:
+                return mapping[key]
+            except KeyError:
+                pass
+        raise KeyError(key)
+
+    def keys(self):
+        result = []
+        seen = set()
+        for mapping in self_maps:
+            for key in mapping:
+                if key not in seen:
+                    result.append(key)
+                    seen.add(key)
+        return result
+
 class ConfigParser(RawConfigParser):
 
     def get(self, section, option, raw=False, vars=None):
@@ -559,16 +591,18 @@
 
         The section DEFAULT is special.
         """
-        d = self._defaults.copy()
+        sectiondict = {}
         try:
-            d.update(self._sections[section])
+            sectiondict = self._sections[section]
         except KeyError:
             if section != DEFAULTSECT:
                 raise NoSectionError(section)
         # Update with the entry specific variables
+        vardict = {}
         if vars:
             for key, value in vars.items():
-                d[self.optionxform(key)] = value
+                vardict[self.optionxform(key)] = value
+        d = _Chainmap(vardict, sectiondict, self._defaults)
         option = self.optionxform(option)
         try:
             value = d[option]


More information about the Python-checkins mailing list