Skip to main content

Python NumPy: How to Catch a NumPy Warning Like an Exception in Python

NumPy operations like dividing by zero, taking the logarithm of a negative number, or overflow in calculations produce warnings rather than raising exceptions. While warnings don't stop your program, they can indicate serious issues in your computations. In some cases, you want to catch these warnings and handle them just like exceptions - logging them, providing fallback values, or stopping execution.

This guide covers several methods to convert NumPy warnings into catchable exceptions.

Understanding the Problem

By default, NumPy operations that produce invalid results emit a warning but continue execution:

import numpy as np

arr = np.array([1.0, 2.0, 3.0])
result = arr / 0

print(result)

Output:

RuntimeWarning: divide by zero encountered in divide
[inf inf inf]

The program continues with inf values instead of stopping. In many scenarios, you want to catch this and handle it explicitly.

The np.errstate() context manager lets you control how NumPy handles floating-point errors within a specific block of code. Setting an error category to 'raise' causes NumPy to raise a FloatingPointError exception:

import numpy as np

arr = np.array([1.0, 5.0, 4.0])

with np.errstate(divide='raise'):
try:
result = arr / 0
except FloatingPointError:
print("❌ Error: Division by zero detected!")

Output:

❌ Error: Division by zero detected!

Available Error Categories

You can control different types of floating-point errors independently:

import numpy as np

# Raise on all floating-point issues
with np.errstate(divide='raise', invalid='raise', over='raise', under='raise'):
try:
result = np.sqrt(-1) # Invalid operation
except FloatingPointError as e:
print(f"Caught: {e}")

Output:

Caught: invalid value encountered in sqrt
CategoryTriggers OnExample
divideDivision by zero1.0 / 0
invalidInvalid operation (e.g., 0/0, sqrt(-1))np.sqrt(-1)
overOverflow (result too large)np.float64(1e308) * 10
underUnderflow (result too small)np.float64(1e-308) / 1e308

Setting All Categories at Once

import numpy as np

with np.errstate(all='raise'):
try:
result = np.array([0.0]) / np.array([0.0]) # 0/0 = invalid
except FloatingPointError as e:
print(f"Caught: {e}")

Output:

Caught: invalid value encountered in divide
Why np.errstate() is recommended

np.errstate() is a context manager, so it only affects the code inside the with block. The original error settings are automatically restored afterward, preventing side effects on other parts of your program.

Using np.seterr() for Global Configuration

np.seterr() changes how NumPy handles floating-point errors globally for the entire program:

import numpy as np

# Save original settings
original_settings = np.seterr(all='raise')

try:
result = np.array([1.0, 2.0]) / 0
except FloatingPointError as e:
print(f"Caught globally: {e}")

# Restore original settings
np.seterr(**original_settings)

Output:

Caught globally: divide by zero encountered in divide

Available Actions

ActionBehavior
'raise'Raise a FloatingPointError exception
'warn'Print a RuntimeWarning (default)
'ignore'Silently ignore the issue
'call'Call a custom function
'print'Print a warning to stdout
'log'Log the warning
np.seterr() affects the entire program

Unlike np.errstate() which is scoped to a with block, np.seterr() changes settings globally. Always save and restore the original settings to avoid unexpected behavior in other parts of your code:

# Save original
old = np.seterr(divide='raise')

# ... your code ...

# Restore original
np.seterr(**old)

Prefer np.errstate() for localized error handling.

Using the warnings Module

Python's built-in warnings module can convert warnings into exceptions, including NumPy's RuntimeWarning:

import warnings
import numpy as np

with warnings.catch_warnings():
warnings.simplefilter("error") # Treat all warnings as errors

try:
result = np.array([1.0, 2.0, 3.0]) / 0
except RuntimeWarning as e:
print(f"Caught warning: {e}")

Output:

Caught warning: divide by zero encountered in divide

Filtering Specific Warning Types

You can target only specific warning categories:

import warnings
import numpy as np

with warnings.catch_warnings():
# Only catch RuntimeWarning, not all warnings
warnings.filterwarnings("error", category=RuntimeWarning)

try:
result = np.log(-1) # Produces RuntimeWarning
except RuntimeWarning as e:
print(f"Caught: {e}")

Output:

Caught: invalid value encountered in log

Practical Example: Safe Division with Fallback

Here's a real-world function that catches division-related warnings and provides fallback values:

import numpy as np

def safe_divide(a, b, default=0.0):
"""Divide arrays a/b, replacing invalid results with a default value."""
with np.errstate(divide='raise', invalid='raise'):
try:
result = a / b
except FloatingPointError:
# Fall back to element-wise handling
result = np.where(b != 0, a / np.where(b != 0, b, 1), default)
return result

numerator = np.array([10, 20, 30, 0])
denominator = np.array([2, 0, 5, 0])

result = safe_divide(numerator, denominator, default=-1)
print("Result:", result)

Output:

Result: [ 5. -1.  6. -1.]

Positions where the denominator is zero are replaced with the default value (-1) instead of producing inf or nan.

Practical Example: Data Validation Pipeline

import numpy as np

def validate_computation(data):
"""Run computation with strict error checking."""
errors = []

with np.errstate(all='raise'):
# Check for division issues
try:
ratios = data['values'] / data['weights']
except FloatingPointError:
errors.append("Division error in ratio calculation")
ratios = np.zeros_like(data['values'])

# Check for log of non-positive values
try:
log_values = np.log(data['values'])
except FloatingPointError:
errors.append("Invalid values for logarithm")
log_values = np.full_like(data['values'], np.nan)

return {
'ratios': ratios,
'log_values': log_values,
'errors': errors
}

data = {
'values': np.array([10.0, 0.0, -5.0, 20.0]),
'weights': np.array([2.0, 0.0, 1.0, 4.0])
}

result = validate_computation(data)
print("Ratios:", result['ratios'])
print("Log values:", result['log_values'])
print("Errors:", result['errors'])

Output:

Ratios: [0. 0. 0. 0.]
Log values: [nan nan nan nan]
Errors: ['Division error in ratio calculation', 'Invalid values for logarithm']

Comparison of Methods

MethodScopeException TypeBest For
np.errstate()Local (with block)FloatingPointErrorRecommended - localized handling
np.seterr()GlobalFloatingPointErrorProgram-wide settings
warnings.catch_warnings()Local (with block)RuntimeWarningCatching all Python warnings

Conclusion

NumPy warnings can mask serious computation errors in your data pipeline.

  • Using np.errstate() with 'raise' is the safest and most Pythonic approach: it converts floating-point issues into catchable FloatingPointError exceptions within a scoped block, without affecting the rest of your program.

  • Use np.seterr() when you need global settings

  • Use warnings module when you want to catch broader Python warning categories.

By treating warnings as exceptions where appropriate, you ensure that invalid computations are detected and handled rather than silently producing incorrect results.