Skip to content

Commit 2e01b75

Browse files
Scott Sandersonbrettcannon
authored andcommitted
bpo-29235: Make cProfile.Profile a context manager (GH-6808)
1 parent 252f6ab commit 2e01b75

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed

Doc/library/profile.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,16 @@ functions:
262262
ps.print_stats()
263263
print(s.getvalue())
264264

265+
The :class:`Profile` class can also be used as a context manager (see
266+
:ref:`typecontextmanager`)::
267+
268+
import cProfile
269+
270+
with cProfile.Profile() as pr:
271+
# ... do something ...
272+
273+
pr.print_stats()
274+
265275
.. method:: enable()
266276

267277
Start collecting profiling data.

Lib/cProfile.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ def runcall(self, func, *args, **kw):
110110
finally:
111111
self.disable()
112112

113+
def __enter__(self):
114+
self.enable()
115+
return self
116+
117+
def __exit__(self, *exc_info):
118+
self.disable()
119+
113120
# ____________________________________________________________
114121

115122
def label(code):

Lib/test/test_cprofile.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,33 @@ def test_module_path_option(self):
4949
# Test successful run
5050
assert_python_ok('-m', 'cProfile', '-m', 'timeit', '-n', '1')
5151

52+
def test_profile_enable_disable(self):
53+
prof = self.profilerclass()
54+
# Make sure we clean ourselves up if the test fails for some reason.
55+
self.addCleanup(prof.disable)
56+
57+
prof.enable()
58+
self.assertIs(sys.getprofile(), prof)
59+
60+
prof.disable()
61+
self.assertIs(sys.getprofile(), None)
62+
63+
def test_profile_as_context_manager(self):
64+
prof = self.profilerclass()
65+
# Make sure we clean ourselves up if the test fails for some reason.
66+
self.addCleanup(prof.disable)
67+
68+
with prof as __enter__return_value:
69+
# profile.__enter__ should return itself.
70+
self.assertIs(prof, __enter__return_value)
71+
72+
# profile should be set as the global profiler inside the
73+
# with-block
74+
self.assertIs(sys.getprofile(), prof)
75+
76+
# profile shouldn't be set once we leave the with-block.
77+
self.assertIs(sys.getprofile(), None)
78+
5279

5380
def test_main():
5481
run_unittest(CProfileTest)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
The :class:`cProfile.Profile` class can now be used as a context manager.
2+
You can profile a block of code by running::
3+
4+
import cProfile
5+
with cProfile.Profile() as profiler:
6+
# ... code to be profiled ...
7+
8+
Patch by Scott Sanderson.

0 commit comments

Comments
 (0)