From 80779571ef34ed079d9f2f0aa0e89a1c61df1049 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Tue, 7 Nov 2017 01:10:42 +0530 Subject: [PATCH 1/4] bpo-21862: Add -m option to cProfile for profiling modules --- Doc/library/profile.rst | 4 +++- Lib/cProfile.py | 35 +++++++++++++++++++++++------------ Lib/test/test_cprofile.py | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst index 68f24abe6f0bd7..b142e5b24f97fb 100644 --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -123,13 +123,15 @@ 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. + 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/Lib/cProfile.py b/Lib/cProfile.py index 1184385ae1f1fe..1f5fb69b6dee75 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 = "runpy.run_module(modname, run_name='__main__')" + globs = { + 'runpy': runpy, + '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 53f8917330296d..ff30e157678921 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', 'random_module_xyz.py') + + # Test successful run + assert_python_ok('-m', 'cProfile', '-m', 'timeit', '-n', '1') + def test_main(): run_unittest(CProfileTest) From 1b4e736537d2aafc193b4ede4da4a8b4b0976438 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Wed, 8 Nov 2017 10:55:18 +0530 Subject: [PATCH 2/4] bpo-21862: Address review comments for -m flag in cProfile --- Doc/library/profile.rst | 4 +++- Doc/whatsnew/3.7.rst | 6 ++++++ Lib/cProfile.py | 4 ++-- Lib/test/test_cprofile.py | 2 +- .../next/Library/2017-11-07-15-19-52.bpo-21862.RwietE.rst | 2 ++ 5 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-11-07-15-19-52.bpo-21862.RwietE.rst diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst index b142e5b24f97fb..0c3a8979898f0b 100644 --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -123,7 +123,7 @@ 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] [-m module] 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 @@ -132,6 +132,8 @@ 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 + 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 6c81a2c3a08984..1ba39fc0472ebd 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 1f5fb69b6dee75..f166a1c4375207 100755 --- a/Lib/cProfile.py +++ b/Lib/cProfile.py @@ -145,9 +145,9 @@ def main(): if len(args) > 0: if options.module: - code = "runpy.run_module(modname, run_name='__main__')" + code = "run_module(modname, run_name='__main__')" globs = { - 'runpy': runpy, + 'run_module': runpy.run_module, 'modname': args[0] } else: diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py index ff30e157678921..07bab5e4576328 100644 --- a/Lib/test/test_cprofile.py +++ b/Lib/test/test_cprofile.py @@ -44,7 +44,7 @@ def test_module_path_option(self): assert_python_failure('-m', 'cProfile', '-m') # Test failure for not-existent module - assert_python_failure('-m', 'cProfile', 'random_module_xyz.py') + assert_python_failure('-m', 'cProfile', 'random_module_xyz') # Test successful run assert_python_ok('-m', 'cProfile', '-m', 'timeit', '-n', '1') 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 00000000000000..6623d1950df3ca --- /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. From da24996830d251c0fd7bf9631875724379b0758c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 8 Nov 2017 10:44:55 +0100 Subject: [PATCH 3/4] Add missing `-m` for proper test operation --- Lib/test/test_cprofile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py index 07bab5e4576328..1430d22504854e 100644 --- a/Lib/test/test_cprofile.py +++ b/Lib/test/test_cprofile.py @@ -44,7 +44,7 @@ def test_module_path_option(self): assert_python_failure('-m', 'cProfile', '-m') # Test failure for not-existent module - assert_python_failure('-m', 'cProfile', 'random_module_xyz') + assert_python_failure('-m', 'cProfile', '-m', 'random_module_xyz') # Test successful run assert_python_ok('-m', 'cProfile', '-m', 'timeit', '-n', '1') From 0714f7ba7da03b5f24b6a5a00e8607c9b41063f7 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 8 Nov 2017 10:47:59 +0100 Subject: [PATCH 4/4] Add description to the `versionadded` tag --- Doc/library/profile.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst index 0c3a8979898f0b..48426a00c9a6c8 100644 --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -133,6 +133,7 @@ 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::