]> granicus.if.org Git - python/commitdiff
Fix #17197: profile/cProfile modules refactored so that code of run() and runctx...
authorGiampaolo Rodola' <g.rodola@gmail.com>
Mon, 25 Feb 2013 10:36:40 +0000 (11:36 +0100)
committerGiampaolo Rodola' <g.rodola@gmail.com>
Mon, 25 Feb 2013 10:36:40 +0000 (11:36 +0100)
Lib/cProfile.py
Lib/profile.py
Misc/NEWS

index 81e722b1ec62f594cd5d00e0edc4a3d9768576ef..1184385ae1f1fe1909f59fc2d79619afcc51e6e4 100755 (executable)
@@ -7,54 +7,20 @@
 __all__ = ["run", "runctx", "Profile"]
 
 import _lsprof
+import profile as _pyprofile
 
 # ____________________________________________________________
 # Simple interface
 
 def run(statement, filename=None, sort=-1):
-    """Run statement under profiler optionally saving results in filename
-
-    This function takes a single argument that can be passed to the
-    "exec" statement, and an optional file name.  In all cases this
-    routine attempts to "exec" its first argument and gather profiling
-    statistics from the execution. If no file name is present, then this
-    function automatically prints a simple profiling report, sorted by the
-    standard name string (file/line/function-name) that is presented in
-    each line.
-    """
-    prof = Profile()
-    result = None
-    try:
-        try:
-            prof = prof.run(statement)
-        except SystemExit:
-            pass
-    finally:
-        if filename is not None:
-            prof.dump_stats(filename)
-        else:
-            result = prof.print_stats(sort)
-    return result
+    return _pyprofile._Utils(Profile).run(statement, filename, sort)
 
 def runctx(statement, globals, locals, filename=None, sort=-1):
-    """Run statement under profiler, supplying your own globals and locals,
-    optionally saving results in filename.
+    return _pyprofile._Utils(Profile).runctx(statement, globals, locals,
+                                             filename, sort)
 
-    statement and filename have the same semantics as profile.run
-    """
-    prof = Profile()
-    result = None
-    try:
-        try:
-            prof = prof.runctx(statement, globals, locals)
-        except SystemExit:
-            pass
-    finally:
-        if filename is not None:
-            prof.dump_stats(filename)
-        else:
-            result = prof.print_stats(sort)
-    return result
+run.__doc__ = _pyprofile.run.__doc__
+runctx.__doc__ = _pyprofile.runctx.__doc__
 
 # ____________________________________________________________
 
index 553f210c133b7cd8a0e004c21f92b07face81f61..5d0e9685a4f1aaf7a057eb58d27bd5122b2f6150 100755 (executable)
@@ -40,6 +40,40 @@ __all__ = ["run", "runctx", "Profile"]
 #       return i_count
 #itimes = integer_timer # replace with C coded timer returning integers
 
+class _Utils:
+    """Support class for utility functions which are shared by
+    profile.py and cProfile.py modules.
+    Not supposed to be used directly.
+    """
+
+    def __init__(self, profiler):
+        self.profiler = profiler
+
+    def run(self, statement, filename, sort):
+        prof = self.profiler()
+        try:
+            prof.run(statement)
+        except SystemExit:
+            pass
+        finally:
+            self._show(prof, filename, sort)
+
+    def runctx(self, statement, globals, locals, filename, sort):
+        prof = self.profiler()
+        try:
+            prof.runctx(statement, globals, locals)
+        except SystemExit:
+            pass
+        finally:
+            self._show(prof, filename, sort)
+
+    def _show(self, prof, filename, sort):
+        if filename is not None:
+            prof.dump_stats(filename)
+        else:
+            prof.print_stats(sort)
+
+
 #**************************************************************************
 # The following are the static member functions for the profiler class
 # Note that an instance of Profile() is *not* needed to call them.
@@ -56,15 +90,7 @@ def run(statement, filename=None, sort=-1):
     standard name string (file/line/function-name) that is presented in
     each line.
     """
-    prof = Profile()
-    try:
-        prof = prof.run(statement)
-    except SystemExit:
-        pass
-    if filename is not None:
-        prof.dump_stats(filename)
-    else:
-        return prof.print_stats(sort)
+    return _Utils(Profile).run(statement, filename, sort)
 
 def runctx(statement, globals, locals, filename=None, sort=-1):
     """Run statement under profiler, supplying your own globals and locals,
@@ -72,16 +98,8 @@ def runctx(statement, globals, locals, filename=None, sort=-1):
 
     statement and filename have the same semantics as profile.run
     """
-    prof = Profile()
-    try:
-        prof = prof.runctx(statement, globals, locals)
-    except SystemExit:
-        pass
-
-    if filename is not None:
-        prof.dump_stats(filename)
-    else:
-        return prof.print_stats(sort)
+    return _Utils(Profile).runctx(statement, globals, locals, filename, sort)
+
 
 class Profile:
     """Profiler class.
index a003684337ac6ffb14880092b5d77f91a1d78e7d..814f2f29d69132ad5a4cb17561fe1e4c83dfd13e 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -263,6 +263,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #17197: profile/cProfile modules refactored so that code of run() and
+  runctx() utility functions is not duplicated in both modules.
+
 - Issue #14720: sqlite3: Convert datetime microseconds correctly.
   Patch by Lowe Thiderman.