Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7973e27

Browse files
CuriousLearnerpitrou
authored andcommitted
bpo-21862: Add -m option to cProfile for profiling modules (#4297)
* bpo-21862: Add -m option to cProfile for profiling modules
1 parent 4fc4def commit 7973e27

5 files changed

Lines changed: 51 additions & 13 deletions

File tree

Doc/library/profile.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,18 @@ them in various ways.
123123
The file :mod:`cProfile` can also be invoked as a script to profile another
124124
script. For example::
125125

126-
python -m cProfile [-o output_file] [-s sort_order] myscript.py
126+
python -m cProfile [-o output_file] [-s sort_order] (-m module | myscript.py)
127127

128128
``-o`` writes the profile results to a file instead of to stdout
129129

130130
``-s`` specifies one of the :func:`~pstats.Stats.sort_stats` sort values to sort
131131
the output by. This only applies when ``-o`` is not supplied.
132132

133+
``-m`` specifies that a module is being profiled instead of a script.
134+
135+
.. versionadded:: 3.7
136+
Added the ``-m`` option.
137+
133138
The :mod:`pstats` module's :class:`~pstats.Stats` class has a variety of methods
134139
for manipulating and printing the data saved into a profile results file::
135140

Doc/whatsnew/3.7.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,12 @@ contextlib
255255
:func:`contextlib.asynccontextmanager` has been added. (Contributed by
256256
Jelle Zijlstra in :issue:`29679`.)
257257

258+
cProfile
259+
--------
260+
261+
cProfile command line now accepts `-m module_name` as an alternative to
262+
script path. (Contributed by Sanyam Khurana in :issue:`21862`.)
263+
258264
crypt
259265
-----
260266

Lib/cProfile.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,20 @@ def label(code):
121121
# ____________________________________________________________
122122

123123
def main():
124-
import os, sys
124+
import os
125+
import sys
126+
import runpy
125127
from optparse import OptionParser
126-
usage = "cProfile.py [-o output_file_path] [-s sort] scriptfile [arg] ..."
128+
usage = "cProfile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ..."
127129
parser = OptionParser(usage=usage)
128130
parser.allow_interspersed_args = False
129131
parser.add_option('-o', '--outfile', dest="outfile",
130132
help="Save stats to <outfile>", default=None)
131133
parser.add_option('-s', '--sort', dest="sort",
132134
help="Sort order when printing to stdout, based on pstats.Stats class",
133135
default=-1)
136+
parser.add_option('-m', dest="module", action="store_true",
137+
help="Profile a library module", default=False)
134138

135139
if not sys.argv[1:]:
136140
parser.print_usage()
@@ -140,16 +144,23 @@ def main():
140144
sys.argv[:] = args
141145

142146
if len(args) > 0:
143-
progname = args[0]
144-
sys.path.insert(0, os.path.dirname(progname))
145-
with open(progname, 'rb') as fp:
146-
code = compile(fp.read(), progname, 'exec')
147-
globs = {
148-
'__file__': progname,
149-
'__name__': '__main__',
150-
'__package__': None,
151-
'__cached__': None,
152-
}
147+
if options.module:
148+
code = "run_module(modname, run_name='__main__')"
149+
globs = {
150+
'run_module': runpy.run_module,
151+
'modname': args[0]
152+
}
153+
else:
154+
progname = args[0]
155+
sys.path.insert(0, os.path.dirname(progname))
156+
with open(progname, 'rb') as fp:
157+
code = compile(fp.read(), progname, 'exec')
158+
globs = {
159+
'__file__': progname,
160+
'__name__': '__main__',
161+
'__package__': None,
162+
'__cached__': None,
163+
}
153164
runctx(code, globs, None, options.outfile, options.sort)
154165
else:
155166
parser.print_usage()

Lib/test/test_cprofile.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# rip off all interesting stuff from test_profile
77
import cProfile
88
from test.test_profile import ProfileTest, regenerate_expected_output
9+
from test.support.script_helper import assert_python_failure, assert_python_ok
910

1011

1112
class CProfileTest(ProfileTest):
@@ -35,6 +36,19 @@ def test_bad_counter_during_dealloc(self):
3536
finally:
3637
unlink(TESTFN)
3738

39+
# Issue 21862
40+
def test_module_path_option(self):
41+
# Test -m switch with modules
42+
43+
# Test that -m switch needs an argument
44+
assert_python_failure('-m', 'cProfile', '-m')
45+
46+
# Test failure for not-existent module
47+
assert_python_failure('-m', 'cProfile', '-m', 'random_module_xyz')
48+
49+
# Test successful run
50+
assert_python_ok('-m', 'cProfile', '-m', 'timeit', '-n', '1')
51+
3852

3953
def test_main():
4054
run_unittest(CProfileTest)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cProfile command line now accepts `-m module_name` as an alternative to
2+
script path. Patch by Sanyam Khurana.

0 commit comments

Comments
 (0)