63

I am doing some simple math recessively in a python script and am getting the follow warning:

"Warning: divide by zero encountered in divide".

To provide some context, I am taking two values and trying to find the percent difference in value (a - b) / a and if its above a certain range then process it, but sometimes the value of a or b is zero.

I want to get rid of this specific warning (at a specific line) but all the information I have found so far seems to show me how to stop all warnings (which I do not want).

When I used to write shell scripts, I could do something like this

code...
more code 2 > error.txt
even more code  

In that example, I would get the warnings for the 'code' and 'even more code' command but not for the second line.

Is this possible?

tmthydvnprt
  • 9,790
  • 8
  • 51
  • 70
Lostsoul
  • 23,230
  • 42
  • 133
  • 217
  • Why not check if a or b == 0 and not do the computation? – AlG Feb 03 '12 at 20:07
  • That isn't a usual Python warning, can you show the code you're running? – Ned Batchelder Feb 03 '12 at 20:07
  • that should be an exception, not a warning, no? can't you catch the `ZeroDivisionError`? – mpen Feb 03 '12 at 20:08
  • I thought of that, but the result(which is zero) is exactly what I want already. I think worst case, I will just do that, but I was curious if there was a way to suppress specific messages in python. – Lostsoul Feb 03 '12 at 20:08
  • It is a warning, I'm using numpy/scipy and I think those modules are generating the error when I'm dividing – Lostsoul Feb 03 '12 at 20:09

3 Answers3

133

If Scipy is using the warnings module, then you can suppress specific warnings. Try this at the beginning of your program:

import warnings
warnings.filterwarnings("ignore", message="divide by zero encountered in divide")

If you want this to apply to only one section of code, then use the warnings context manager:

import warnings
with warnings.catch_warnings():
    warnings.filterwarnings("ignore", message="divide by zero encountered in divide")
    # .. your divide-by-zero code ..
Ned Batchelder
  • 345,440
  • 70
  • 544
  • 649
  • How? I saw I can turn off all warnings but is it possible to target a specific line of code? – Lostsoul Feb 03 '12 at 20:11
  • oh just saw your update!..Thanks that was what I was looking for. One more question, Is there a specific way to find the warning message or is it simply just what's coming on the screen? If I get "Warning: your code sucks, lostsoul!", then I can just add that to the message variable above and it would work? – Lostsoul Feb 03 '12 at 20:13
  • 14
    Nice answer. Actually it took me a surprising amount of googling to find this ultra-simple explanation of how to ignore warnings. @Lostsoul you can use message='regex matching message' to catch warnings by message, and there are also lineno= and module= arguments to catch by line number and module name. – cxrodgers Feb 07 '13 at 23:02
14

I'd avoid the division-by-zero in the first place:

if a == 0:
    # Break out early

# Otherwise the ratio makes sense

If you do want to squash that particular numpy warning on a single line, numpy provides a way:

with numpy.errstate(divide='ignore'):
    # The problematic line
Blender
  • 275,078
  • 51
  • 420
  • 480
  • Thanks Blender, that was my first thought but I was just curious if there was a way to get suppress a specific warning. If there is no way(or its crazy complicated then I will def follow your approach) – Lostsoul Feb 03 '12 at 20:10
  • 1
    if he really is doing `(a-b)/a` then checking if either a or b is zero is silly. he just needs to check a! – mpen Feb 03 '12 at 20:12
  • @Mark: That's what I originally thought, but when the OP said **but sometimes the value of a or b is zero**, that confused me. – Blender Feb 03 '12 at 20:13
  • 2
    @Blender: It's like those questions you got in school where they sometimes gave you extra information (b may be 0) that's not really relevant to solving the problem :D – mpen Feb 03 '12 at 23:42
1

Blenders answer is perfectly fitting the problem. Maybe someone is interested in another general approach to catch specific warnings with either regex or the line number:

surpress a warning caused by a specific line, here line 113:

import warnings
warnings.simplefilter('ignore',lineno=113)

This approach has the disadvantage, that each time you change something in the code you need to readjust the lineno. The other option is to catch a warning using regex. The following code will return

import warnings
warnings.filterwarnings('ignore', message='.*show', )
warnings.warn('Do not do this!')
warnings.warn('Do not show this message')
>>> UserWarning: Do not do this!
        warnings.warn('Do not do this!')

The dot before the *-symbol is neccessary as otherwise an error is returned

error: nothing to repeat

which is discussed in this thread

Jakob
  • 36
  • 3