From a91ff1423fbd57e7bd0853ac494d8cdea1fb5bb9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 16 Feb 2014 23:53:38 +0100 Subject: Issue #20616: Add a format() method to tracemalloc.Traceback. --- Doc/library/tracemalloc.rst | 31 ++++++++++++++++++++++++------- Lib/test/test_tracemalloc.py | 20 ++++++++++++++++++++ Lib/tracemalloc.py | 13 +++++++++++++ Misc/NEWS | 2 ++ 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/Doc/library/tracemalloc.rst b/Doc/library/tracemalloc.rst index e49d4ca..b79c5f6 100644 --- a/Doc/library/tracemalloc.rst +++ b/Doc/library/tracemalloc.rst @@ -118,7 +118,6 @@ Get the traceback of a memory block Code to display the traceback of the biggest memory block:: - import linecache import tracemalloc # Store 25 frames @@ -132,12 +131,8 @@ Code to display the traceback of the biggest memory block:: # pick the biggest memory block stat = top_stats[0] print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024)) - for frame in stat.traceback: - print(' File "%s", line %s' % (frame.filename, frame.lineno)) - line = linecache.getline(frame.filename, frame.lineno) - line = line.strip() - if line: - print(' ' + line) + for line in stat.traceback.format(): + print(line) Example of output of the Python test suite (traceback limited to 25 frames):: @@ -602,4 +597,26 @@ Traceback The :attr:`Trace.traceback` attribute is an instance of :class:`Traceback` instance. + .. method:: format(limit=None) + + Format the traceback as a list of lines with newlines. Use the + :mod:`linecache` module to retrieve lines from the source code. If + *limit* is set, only format the *limit* most recent frames. + + Similar to the :func:`traceback.format_tb` function, except that + :meth:`format` does not include newlines. + + Example:: + + print("Traceback (most recent call first):") + for line in traceback: + print(line) + + Output:: + + Traceback (most recent call first): + File "test.py", line 9 + obj = Object() + File "test.py", line 12 + tb = tracemalloc.get_object_traceback(f()) diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py index 3d2333f..d1e5aef 100644 --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -510,6 +510,26 @@ class TestSnapshot(unittest.TestCase): self.assertEqual(traceback[:2], (traceback[0], traceback[1])) + def test_format_traceback(self): + snapshot, snapshot2 = create_snapshots() + def getline(filename, lineno): + return ' <%s, %s>' % (filename, lineno) + with unittest.mock.patch('tracemalloc.linecache.getline', + side_effect=getline): + tb = snapshot.traces[0].traceback + self.assertEqual(tb.format(), + [' File "a.py", line 2', + ' ', + ' File "b.py", line 4', + ' ']) + + self.assertEqual(tb.format(limit=1), + [' File "a.py", line 2', + ' ']) + + self.assertEqual(tb.format(limit=-1), + []) + class TestFilters(unittest.TestCase): maxDiff = 2048 diff --git a/Lib/tracemalloc.py b/Lib/tracemalloc.py index b075946..6f0a234 100644 --- a/Lib/tracemalloc.py +++ b/Lib/tracemalloc.py @@ -1,6 +1,7 @@ from collections import Sequence from functools import total_ordering import fnmatch +import linecache import os.path import pickle @@ -205,6 +206,18 @@ class Traceback(Sequence): def __repr__(self): return "" % (tuple(self),) + def format(self, limit=None): + lines = [] + if limit is not None and limit < 0: + return lines + for frame in self[:limit]: + lines.append(' File "%s", line %s' + % (frame.filename, frame.lineno)) + line = linecache.getline(frame.filename, frame.lineno).strip() + if line: + lines.append(' %s' % line) + return lines + def get_object_traceback(obj): """ diff --git a/Misc/NEWS b/Misc/NEWS index 4a717fc..48b2b89 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,6 +23,8 @@ Core and Builtins Library ------- +- Issue #20616: Add a format() method to tracemalloc.Traceback. + - Issue #19744: the ensurepip installation step now just prints a warning to stderr rather than failing outright if SSL/TLS is unavailable. This allows local installation of POSIX builds without SSL/TLS support. -- cgit v0.12