You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[ENH]: Make "No artists with labels found to put in legend" a warning #27145
When I receive this issue, it's hard to debug and find the specific call to ax.legend() if I can't raise Warnings to Exceptions. I sometimes nest plotting functions in order to draw the same plot different ways or arrange plots in a composite figure, depending upon the presentation.
No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
Proposed solution
Make this a true UserWarning. Currently, it's a logging.LogRecord of level=logging.Warning.
Additional pro: In the future, it would be easier to find and work on this warning if it is, in fact, a true Warning.
Con: It won't be handled by the logging infrastructure. But legend.py uses the default module logger, and the only LogRecord that it emits is this one. The only situation I could think of where this might matter is if a user has some override of global logging setup (by calling logging.setLoggerClass()) but does not apply a similar philosophy to capturing warnings in STDERR.
This is related to #23422 though this one is a little more ambiguous if it should actually be a warning or not as the user can suppress the warning by either adding a label or removing the legend call.
Thanks for the link :) My issue is definitely an example of @mwaskom's point that "you can convert a warning to an error and then drop into a debugger to figure out what's happening"
Also, I'm not sure I understand how its ambiguous? Your statement:
the user can suppress the warning by either adding a label or removing the legend call.
sounds like the standard, "the issue is avoidable and the client application should be modified to eliminate the warning." I can't think of a situation where a user would legitimately intend to call .legend() without labels. Matplotlib won't draw a legend when it triggers the warning.
TL;DR: logging was added to this module at a time when you were making the package-wide effort of replacing the old Verbose class with python's standard logging. I think adding this particular logging case (and perhaps others) was consumed in effort, and the warnings vs logging choice wasn't given serious discussion in the original planning & review.
Doing a bit of git blame investigation, it looks like this case was added in #9324, which sought to fix #9320, a regression in 2.1 where it seems labels/handles behaved differently as kwargs vs positional args. The PR included code to warn about missing handles, incl the case of a leading underscore in a label. Early in the PR you were using warnings.warn, but mentioned
I’d suggest we just strip the illegal underscore and warn (or logging.warning 😉) or set it to an empty string.
That was the extent of discussion I could find about logging vs warning. Another commit later amended the message (#20956) but didn't touch on logging vs warning.
A pickaxe search of the git log for "logging" around the same time finds another commit (844877c) & PR (#9313) that address a discussion (#9302) about replacing matplotlib's old Verbose class with python's standard logging. A grep search of the documentation diff explains it's better to use logging than print() and links to the logging tutorial's distinction between warnings and logging, but stops there. The issue discussion never addresses the difference between warning and logging modules, but does note that the old Verbose class did not have equivalents to logging.WARNING, logging.ERROR, or logging.CRITICAL. (comment)
Thanks for the archeology 🚀! I conclude that the current state has evolved organically and there has probably not been a conscious decision between logging and warnings for this specific case.
Either way,
I can't think of a situation where a user would legitimately intend to call .legend() without labels.
plus
the user can suppress the warning by either adding a label or removing the legend call.
is a clear indication for me that this should be a UserWarning.
Activity
jklymak commentedon Oct 19, 2023
This is related to #23422 though this one is a little more ambiguous if it should actually be a warning or not as the user can suppress the warning by either adding a label or removing the legend call.
Jacob-Stevens-Haas commentedon Oct 19, 2023
Thanks for the link :) My issue is definitely an example of @mwaskom's point that "you can convert a warning to an error and then drop into a debugger to figure out what's happening"
Also, I'm not sure I understand how its ambiguous? Your statement:
sounds like the standard, "the issue is avoidable and the client application should be modified to eliminate the warning." I can't think of a situation where a user would legitimately intend to call
.legend()without labels. Matplotlib won't draw a legend when it triggers the warning.jklymak commentedon Oct 19, 2023
I agree, but I don't remember the original rationale for a logging call versus warning, and the rule itself is a bit ambiguous.
Jacob-Stevens-Haas commentedon Oct 20, 2023
TL;DR: logging was added to this module at a time when you were making the package-wide effort of replacing the old
Verboseclass with python's standardlogging. I think adding this particular logging case (and perhaps others) was consumed in effort, and thewarningsvsloggingchoice wasn't given serious discussion in the original planning & review.Doing a bit of
git blameinvestigation, it looks like this case was added in #9324, which sought to fix #9320, a regression in 2.1 where it seems labels/handles behaved differently as kwargs vs positional args. The PR included code to warn about missing handles, incl the case of a leading underscore in a label. Early in the PR you were usingwarnings.warn, but mentionedThat was the extent of discussion I could find about logging vs warning. Another commit later amended the message (#20956) but didn't touch on logging vs warning.
A pickaxe search of the git log for "logging" around the same time finds another commit (844877c) & PR (#9313) that address a discussion (#9302) about replacing matplotlib's old
Verboseclass with python's standard logging. A grep search of the documentation diff explains it's better to use logging thanprint()and links to the logging tutorial's distinction betweenwarningsandlogging, but stops there. The issue discussion never addresses the difference betweenwarningandloggingmodules, but does note that the oldVerboseclass did not have equivalents tologging.WARNING,logging.ERROR, orlogging.CRITICAL. (comment)timhoffm commentedon Oct 20, 2023
Thanks for the archeology 🚀! I conclude that the current state has evolved organically and there has probably not been a conscious decision between logging and warnings for this specific case.
Either way,
plus
is a clear indication for me that this should be a
UserWarning.jklymak commentedon Oct 22, 2023
@Jacob-Stevens-Haas Did you have bandwidth to put in a PR to change this?
Jacob-Stevens-Haas commentedon Oct 23, 2023
I think so! Got the dev environment/install up and working, and all tests (at least all relevant tests) pass, so I can start a PR.
Jacob-Stevens-Haas commentedon Oct 23, 2023
Am I supposed to add a file to matplotlib/doc/users/next_whats_new for this kind of change?
Also, should I keep the default module logger definition
log = logging.getLogger(__name__)? It no longer is accessed.ENH: Change logging to warning when creating a legend with no labels (#…