On ResourceWarning, log traceback where the object was allocated

Issue #26567:

* Add a new function PyErr_ResourceWarning() function to pass the destroyed
  object
* Add a source attribute to warnings.WarningMessage
* Add warnings._showwarnmsg() which uses tracemalloc to get the traceback where
  source object was allocated.
This commit is contained in:
Victor Stinner 2016-03-19 01:03:51 +01:00
parent 1231a4615f
commit 914cde89d4
11 changed files with 175 additions and 40 deletions

View file

@ -2,6 +2,7 @@
import sys
__all__ = ["warn", "warn_explicit", "showwarning",
"formatwarning", "filterwarnings", "simplefilter",
"resetwarnings", "catch_warnings"]
@ -66,6 +67,18 @@ def _formatwarnmsg(msg):
if line:
line = line.strip()
s += " %s\n" % line
if msg.source is not None:
import tracemalloc
tb = tracemalloc.get_object_traceback(msg.source)
if tb is not None:
s += 'Object allocated at (most recent call first):\n'
for frame in tb:
s += (' File "%s", lineno %s\n'
% (frame.filename, frame.lineno))
line = linecache.getline(frame.filename, frame.lineno)
if line:
line = line.strip()
s += ' %s\n' % line
return s
def filterwarnings(action, message="", category=Warning, module="", lineno=0,
@ -267,7 +280,8 @@ def warn(message, category=None, stacklevel=1):
globals)
def warn_explicit(message, category, filename, lineno,
module=None, registry=None, module_globals=None):
module=None, registry=None, module_globals=None,
source=None):
lineno = int(lineno)
if module is None:
module = filename or "<unknown>"
@ -333,17 +347,17 @@ def warn_explicit(message, category, filename, lineno,
"Unrecognized action (%r) in warnings.filters:\n %s" %
(action, item))
# Print message and context
msg = WarningMessage(message, category, filename, lineno)
msg = WarningMessage(message, category, filename, lineno, source)
_showwarnmsg(msg)
class WarningMessage(object):
_WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
"line")
"line", "source")
def __init__(self, message, category, filename, lineno, file=None,
line=None):
line=None, source=None):
local_values = locals()
for attr in self._WARNING_DETAILS:
setattr(self, attr, local_values[attr])