[Python-checkins] bpo-21862: Add -m option to cProfile for profiling modules (#4297)

Antoine Pitrou webhook-mailer at python.org
Wed Nov 8 05:51:03 EST 2017


https://github.com/python/cpython/commit/7973e279a21999f134aff92dd6d344ec4591fae9
commit: 7973e279a21999f134aff92dd6d344ec4591fae9
branch: master
author: Sanyam Khurana <8039608+CuriousLearner at users.noreply.github.com>
committer: Antoine Pitrou <pitrou at free.fr>
date: 2017-11-08T11:50:56+01:00
summary:

bpo-21862: Add -m option to cProfile for profiling modules (#4297)

* bpo-21862: Add -m option to cProfile for profiling modules

files:
A Misc/NEWS.d/next/Library/2017-11-07-15-19-52.bpo-21862.RwietE.rst
M Doc/library/profile.rst
M Doc/whatsnew/3.7.rst
M Lib/cProfile.py
M Lib/test/test_cprofile.py

diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst
index 68f24abe6f0..48426a00c9a 100644
--- a/Doc/library/profile.rst
+++ b/Doc/library/profile.rst
@@ -123,13 +123,18 @@ them in various ways.
 The file :mod:`cProfile` can also be invoked as a script to profile another
 script.  For example::
 
-   python -m cProfile [-o output_file] [-s sort_order] myscript.py
+   python -m cProfile [-o output_file] [-s sort_order] (-m module | myscript.py)
 
 ``-o`` writes the profile results to a file instead of to stdout
 
 ``-s`` specifies one of the :func:`~pstats.Stats.sort_stats` sort values to sort
 the output by. This only applies when ``-o`` is not supplied.
 
+``-m`` specifies that a module is being profiled instead of a script.
+
+   .. versionadded:: 3.7
+      Added the ``-m`` option.
+
 The :mod:`pstats` module's :class:`~pstats.Stats` class has a variety of methods
 for manipulating and printing the data saved into a profile results file::
 
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index af722be2806..9ac7c9d3985 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -255,6 +255,12 @@ contextlib
 :func:`contextlib.asynccontextmanager` has been added. (Contributed by
 Jelle Zijlstra in :issue:`29679`.)
 
+cProfile
+--------
+
+cProfile command line now accepts `-m module_name` as an alternative to
+script path. (Contributed by Sanyam Khurana in :issue:`21862`.)
+
 crypt
 -----
 
diff --git a/Lib/cProfile.py b/Lib/cProfile.py
index 1184385ae1f..f166a1c4375 100755
--- a/Lib/cProfile.py
+++ b/Lib/cProfile.py
@@ -121,9 +121,11 @@ def label(code):
 # ____________________________________________________________
 
 def main():
-    import os, sys
+    import os
+    import sys
+    import runpy
     from optparse import OptionParser
-    usage = "cProfile.py [-o output_file_path] [-s sort] scriptfile [arg] ..."
+    usage = "cProfile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ..."
     parser = OptionParser(usage=usage)
     parser.allow_interspersed_args = False
     parser.add_option('-o', '--outfile', dest="outfile",
@@ -131,6 +133,8 @@ def main():
     parser.add_option('-s', '--sort', dest="sort",
         help="Sort order when printing to stdout, based on pstats.Stats class",
         default=-1)
+    parser.add_option('-m', dest="module", action="store_true",
+        help="Profile a library module", default=False)
 
     if not sys.argv[1:]:
         parser.print_usage()
@@ -140,16 +144,23 @@ def main():
     sys.argv[:] = args
 
     if len(args) > 0:
-        progname = args[0]
-        sys.path.insert(0, os.path.dirname(progname))
-        with open(progname, 'rb') as fp:
-            code = compile(fp.read(), progname, 'exec')
-        globs = {
-            '__file__': progname,
-            '__name__': '__main__',
-            '__package__': None,
-            '__cached__': None,
-        }
+        if options.module:
+            code = "run_module(modname, run_name='__main__')"
+            globs = {
+                'run_module': runpy.run_module,
+                'modname': args[0]
+            }
+        else:
+            progname = args[0]
+            sys.path.insert(0, os.path.dirname(progname))
+            with open(progname, 'rb') as fp:
+                code = compile(fp.read(), progname, 'exec')
+            globs = {
+                '__file__': progname,
+                '__name__': '__main__',
+                '__package__': None,
+                '__cached__': None,
+            }
         runctx(code, globs, None, options.outfile, options.sort)
     else:
         parser.print_usage()
diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py
index 53f89173302..1430d225048 100644
--- a/Lib/test/test_cprofile.py
+++ b/Lib/test/test_cprofile.py
@@ -6,6 +6,7 @@
 # rip off all interesting stuff from test_profile
 import cProfile
 from test.test_profile import ProfileTest, regenerate_expected_output
+from test.support.script_helper import assert_python_failure, assert_python_ok
 
 
 class CProfileTest(ProfileTest):
@@ -35,6 +36,19 @@ def test_bad_counter_during_dealloc(self):
         finally:
             unlink(TESTFN)
 
+    # Issue 21862
+    def test_module_path_option(self):
+        # Test -m switch with modules
+
+        # Test that -m switch needs an argument
+        assert_python_failure('-m', 'cProfile', '-m')
+
+        # Test failure for not-existent module
+        assert_python_failure('-m', 'cProfile', '-m', 'random_module_xyz')
+
+        # Test successful run
+        assert_python_ok('-m', 'cProfile', '-m', 'timeit', '-n', '1')
+
 
 def test_main():
     run_unittest(CProfileTest)
diff --git a/Misc/NEWS.d/next/Library/2017-11-07-15-19-52.bpo-21862.RwietE.rst b/Misc/NEWS.d/next/Library/2017-11-07-15-19-52.bpo-21862.RwietE.rst
new file mode 100644
index 00000000000..6623d1950df
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-11-07-15-19-52.bpo-21862.RwietE.rst
@@ -0,0 +1,2 @@
+cProfile command line now accepts `-m module_name` as an alternative to
+script path. Patch by Sanyam Khurana.



More information about the Python-checkins mailing list