Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FutureWarnings should specify a stacklevel #9584

Closed
njsmith opened this issue Mar 4, 2015 · 4 comments
Closed

FutureWarnings should specify a stacklevel #9584

njsmith opened this issue Mar 4, 2015 · 4 comments
Labels
Deprecate Functionality to remove in pandas
Milestone

Comments

@njsmith
Copy link

njsmith commented Mar 4, 2015

Running my test suite, I see:

/home/njs/.user-python2.7-64bit-3/local/lib/python2.7/site-packages/pandas/core/categorical.py:443: FutureWarning: Accessing 'levels' is deprecated, use 'categories'
  warn("Accessing 'levels' is deprecated, use 'categories'", FutureWarning)
/home/njs/.user-python2.7-64bit-3/local/lib/python2.7/site-packages/pandas/core/categorical.py:291: RuntimeWarning: Values and categories have different dtypes. Did you mean to use
'Categorical.from_codes(codes, categories)'?
  "'Categorical.from_codes(codes, categories)'?", RuntimeWarning)
/home/njs/.user-python2.7-64bit-3/local/lib/python2.7/site-packages/pandas/core/categorical.py:295: RuntimeWarning: None of the categories were found in values. Did you mean to use
'Categorical.from_codes(codes, categories)'?
  "'Categorical.from_codes(codes, categories)'?", RuntimeWarning)
./home/njs/.user-python2.7-64bit-3/local/lib/python2.7/site-packages/pandas/core/categorical.py:395: FutureWarning: 'labels' is deprecated. Use 'codes' instead
  warnings.warn("'labels' is deprecated. Use 'codes' instead", FutureWarning)

Okay, fair enough. But the problem is that all of the listed lines of code are inside pandas, so I have no idea which parts of my code are actually doing the wrong thing. warnings.warn provides a stacklevel argument, where the idea is that you should pass a non-zero value so that warnings are attributed to the code that actually needs to be changed. E.g., stacklevel=1 means that the code which is doing something wrong is the code which called the function containing the call to warnings.warn.

@jorisvandenbossche jorisvandenbossche added the Deprecate Functionality to remove in pandas label Jun 2, 2015
@jorisvandenbossche jorisvandenbossche added this to the 0.17.0 milestone Jun 2, 2015
@jorisvandenbossche jorisvandenbossche changed the title pandas Categorical warnings are issued for the wrong code FutureWarnings should specify a stacklevel Jun 2, 2015
@jorisvandenbossche
Copy link
Member

@njsmith I changed the title, as this is not specific to the categorical example

This was brought to my attention again by the discussion in ipython about changing the default visibility of DeprecationWarnings (ipython/ipython#8478)

Basically, in plain warning calls, we should use stacklevel=2

@njsmith
Copy link
Author

njsmith commented Jun 2, 2015

Rule of thumb: Calling warnings.warn without specifying a stacklevel= is always a bug.

Here's a summary of what's at stake, since as @jorisvandenbossche pointed out in the ipython discussion the docs are somewhat confusing. It's actually pretty simple. Say I have this code:

def f():
    warnings.warn("this is deprecated", category=DeprecationWarning, stacklevel=X)

def g():
    f()

If X is 1 (the default), then Python will print a warning saying "f is doing something wrong -- it's using deprecated functionality". If X is 2 (what you usually want, esp. for deprecation warnings), then Python will print a warning saying "g is doing something wrong -- it's using deprecated functionality".

@jorisvandenbossche
Copy link
Member

Thanks @njsmith for the overview!

For pandas it means that

  • most direct uses of FutureWarning (inside functions) need a stacklevel=2
  • we have a deprecate(..) function: here stacklevel=2 works as well (has only to be changed in utils/decorators.py
  • we have a deprecate_kwarg decorator: I tested this one, and apparantly a stacklevel=2 is also the correct one
  • only for the ones on import (eg rpy: https://github.com/pydata/pandas/blob/master/pandas/rpy/__init__.py) we don't have to change anything (as you cannot get this right for all python versions -> @njsmith correct?)

@njsmith
Copy link
Author

njsmith commented Jun 5, 2015

For warn-on-import for deprecated modules/packages, you should also use stacklevel=2. This works correctly on Python 2.7 (so... like 80%+ of your users), and will hopefully get fixed to work correctly on python 3 as well (see: https://bugs.python.org/issue24305)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Deprecate Functionality to remove in pandas
Projects
None yet
Development

No branches or pull requests

2 participants