Kaydet (Commit) ad1a25f4 authored tarafından Mario Corchero's avatar Mario Corchero Kaydeden (comit) Nick Coghlan

bpo-32512: Add -m option to profile for profiling modules (#5132)

The new option in the CLI of the profile module allow to profile
executable modules. This change follows the same implementation as the
one already present in `cProfile`.

As the argument is now present on both modules, move the tests to the
common test case to be run with profile as well.
üst 2810dd7b
...@@ -120,8 +120,8 @@ results to a file by specifying a filename to the :func:`run` function:: ...@@ -120,8 +120,8 @@ results to a file by specifying a filename to the :func:`run` function::
The :class:`pstats.Stats` class reads profile results from a file and formats The :class:`pstats.Stats` class reads profile results from a file and formats
them in various ways. them in various ways.
The file :mod:`cProfile` can also be invoked as a script to profile another The files :mod:`cProfile` and :mod:`profile` can also be invoked as a script to
script. For example:: 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)
...@@ -133,7 +133,10 @@ the output by. This only applies when ``-o`` is not supplied. ...@@ -133,7 +133,10 @@ the output by. This only applies when ``-o`` is not supplied.
``-m`` specifies that a module is being profiled instead of a script. ``-m`` specifies that a module is being profiled instead of a script.
.. versionadded:: 3.7 .. versionadded:: 3.7
Added the ``-m`` option. Added the ``-m`` option to :mod:`cProfile`.
.. versionadded:: 3.8
Added the ``-m`` option to :mod:`profile`.
The :mod:`pstats` module's :class:`~pstats.Stats` class has a variety of methods 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:: for manipulating and printing the data saved into a profile results file::
......
...@@ -553,11 +553,13 @@ def main(): ...@@ -553,11 +553,13 @@ def main():
import os import os
from optparse import OptionParser from optparse import OptionParser
usage = "profile.py [-o output_file_path] [-s sort] scriptfile [arg] ..." usage = "profile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ..."
parser = OptionParser(usage=usage) parser = OptionParser(usage=usage)
parser.allow_interspersed_args = False parser.allow_interspersed_args = False
parser.add_option('-o', '--outfile', dest="outfile", parser.add_option('-o', '--outfile', dest="outfile",
help="Save stats to <outfile>", default=None) help="Save stats to <outfile>", default=None)
parser.add_option('-m', dest="module", action="store_true",
help="Profile a library module.", default=False)
parser.add_option('-s', '--sort', dest="sort", parser.add_option('-s', '--sort', dest="sort",
help="Sort order when printing to stdout, based on pstats.Stats class", help="Sort order when printing to stdout, based on pstats.Stats class",
default=-1) default=-1)
...@@ -570,6 +572,14 @@ def main(): ...@@ -570,6 +572,14 @@ def main():
sys.argv[:] = args sys.argv[:] = args
if len(args) > 0: if len(args) > 0:
if options.module:
import runpy
code = "run_module(modname, run_name='__main__')"
globs = {
'run_module': runpy.run_module,
'modname': args[0]
}
else:
progname = args[0] progname = args[0]
sys.path.insert(0, os.path.dirname(progname)) sys.path.insert(0, os.path.dirname(progname))
with open(progname, 'rb') as fp: with open(progname, 'rb') as fp:
......
...@@ -37,19 +37,6 @@ class CProfileTest(ProfileTest): ...@@ -37,19 +37,6 @@ class CProfileTest(ProfileTest):
finally: finally:
unlink(TESTFN) 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_profile_enable_disable(self): def test_profile_enable_disable(self):
prof = self.profilerclass() prof = self.profilerclass()
# Make sure we clean ourselves up if the test fails for some reason. # Make sure we clean ourselves up if the test fails for some reason.
......
...@@ -11,6 +11,7 @@ from contextlib import contextmanager ...@@ -11,6 +11,7 @@ from contextlib import contextmanager
import profile import profile
from test.profilee import testfunc, timer from test.profilee import testfunc, timer
from test.support.script_helper import assert_python_failure, assert_python_ok
class ProfileTest(unittest.TestCase): class ProfileTest(unittest.TestCase):
...@@ -98,6 +99,18 @@ class ProfileTest(unittest.TestCase): ...@@ -98,6 +99,18 @@ class ProfileTest(unittest.TestCase):
filename=TESTFN) filename=TESTFN)
self.assertTrue(os.path.exists(TESTFN)) self.assertTrue(os.path.exists(TESTFN))
def test_run_profile_as_module(self):
# Test that -m switch needs an argument
assert_python_failure('-m', self.profilermodule.__name__, '-m')
# Test failure for not-existent module
assert_python_failure('-m', self.profilermodule.__name__,
'-m', 'random_module_xyz')
# Test successful run
assert_python_ok('-m', self.profilermodule.__name__,
'-m', 'timeit', '-n', '1')
def regenerate_expected_output(filename, cls): def regenerate_expected_output(filename, cls):
filename = filename.rstrip('co') filename = filename.rstrip('co')
......
:mod:`profile` CLI accepts `-m module_name` as an alternative to
script path.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment