[Python-checkins] r53058 - sandbox/trunk/import_in_py/importbench.py

brett.cannon python-checkins at python.org
Mon Dec 18 22:29:28 CET 2006


Author: brett.cannon
Date: Mon Dec 18 22:29:28 2006
New Revision: 53058

Modified:
   sandbox/trunk/import_in_py/importbench.py
Log:
Add a test for a guaranteed import failure.

Also add some infrastructure code for preserving import state between
benchmarks and for creating temporary .py/.pyc files. 


Modified: sandbox/trunk/import_in_py/importbench.py
==============================================================================
--- sandbox/trunk/import_in_py/importbench.py	(original)
+++ sandbox/trunk/import_in_py/importbench.py	Mon Dec 18 22:29:28 2006
@@ -1,16 +1,101 @@
+from py_compile import compile as compile_to_pyc
+import os
+import sys
+import tempfile
 from timeit import Timer
 
-def bench_sys_modules(times=100000, repeat=1):
+
+def save_import_state(fxn):
+    """Backup and restore the import state."""
+    def inner(*args, **kwargs):
+        modules = sys.modules.copy()
+        path = sys.path[:]
+        meta_path = sys.meta_path[:]
+        path_importer_cache = sys.path_importer_cache.copy()
+        path_hooks = sys.path_hooks[:]
+        try:
+            return fxn(*args, **kwargs)
+        finally:
+            sys.modules.clear()
+            sys.modules.update(modules)
+            sys.path = path
+            sys.meta_path = meta_path
+            sys.path_importer_cache.clear()
+            sys.path_importer_cache.update(path_importer_cache)
+            sys.path_hooks = path_hooks
+
+    inner.__name__ = fxn.__name__
+    return inner
+
+class PyPycFiles(object):
+
+    """Create .py and .pyc files for importing."""
+    
+    def __init__(self, py=True, pyc=True, module_name="tempmod"):
+        """Specify what type of files to create."""
+        self.py = py
+        self.pyc = pyc
+        self.module_name = module_name
+        
+    def __enter__(self):
+        """Create requested files."""
+        self.directory = tempfile.gettempdir()
+        self.py_path = os.path.join(self.directory, self.module_name + '.py')
+        with open(self.py_path, 'w') as py_file:
+            py_file.write("# Temporary file for benchmarking import.")
+        if self.pyc:
+            compile_to_pyc(self.py_path, doraise=True)
+            self.pyc_path = self.py_path + ('c' if __debug__ else 'o')
+        if not self.py:
+            os.remove(self.py_path)
+        sys.path.append(self.directory)
+        return self
+        
+    def __exit__(self, *args):
+        """Clean up created state."""
+        if self.py:
+            os.remove(self.py_path)
+        if self.pyc:
+            os.remove(self.pyc_path)
+
+
+ at save_import_state
+def bench_sys_modules(times, repeat):
     """Benchmark returning a modules from sys.modules."""
-    # We can safely assume timeit has already been imported.
-    timer = Timer("__import__('timeit', {}, {}, [], 0)")
-    return timer.repeat(repeat, times)
+    sys.path = []
+    sys.meta_path = []
+    sys.path_importer_cache.clear()
+    with PyPycFiles() as py_pyc_state:
+        # Force the module into sys.modules .
+        __import__(py_pyc_state.module_name, {})
+        timer = Timer("__import__(%r, {}, {}, [], 0)" % py_pyc_state.module_name)
+        return timer.repeat(repeat, times)
+
+ at save_import_state
+def bench_nonexistent_module(times, repeat):
+    """How expensive is an import failure (with a single entry on sys.path)?"""
+    # Verify that the module does not exist.
+    sys.path = []
+    sys.meta_path = []
+    bad_name = 'sadfflkjsdf'
+    # Have at least one entry on sys.path.
+    with PyPycFiles():
+        # Make sure the fake module name is not actually real.
+        try:
+            __import__(bad_name)
+        except ImportError:
+            pass
+        else:
+            raise Exception("supposed non-existent module actually exists")
+        timer = Timer("try:__import__(%r, {}, {}, [], 0)\nexcept ImportError:pass" %
+                        bad_name)
+        return timer.repeat(repeat, times)
     
     
 def main():
     for name, item in globals().iteritems():
         if name.startswith('bench_'):
-            timings = item()
+            timings = item(10000, 1)
             print "%s: %s" % (item.__name__, timings)
             
             


More information about the Python-checkins mailing list