Xử lý ZeroDivisionError trong Python: Cách khắc phục và phòng ngừa thực tế

beginner🐍 Python2026-06-24| Python 3.x (Mọi hệ điều hành: Windows, macOS, Linux)

Error Message

ZeroDivisionError: division by zero
#python#debugging#pandas#numpy#xử-lý-lỗi

Bối cảnhKhông gì làm gián đoạn một tập lệnh xử lý dữ liệu đang chạy lâu nhanh hơn lỗi ZeroDivisionError. Gần đây, tôi đã dành hai giờ để xử lý một tập dữ liệu 500.000 hàng cho một dashboard marketing, nhưng script lại bị sập ở hàng 489.012. Vấn đề là gì? Tôi đang tính Tỷ lệ nhấp (CTR) bằng cách chia số lượt nhấp cho số lượt hiển thị. Một vài chiến dịch ngách có chính xác không lượt hiển thị, và Python không biết cách xử lý phép toán này.

Python rất nghiêm ngặt về phép chia. Trong khi các ngôn ngữ như JavaScript có thể trả về Infinity, Python sẽ đưa ra một ngoại lệ và dừng thực thi ngay lập tức. Điều này xảy ra bất cứ khi nào số chia trong phép chia (/, //) hoặc phép chia lấy dư (%) bằng không.

Quy trình gỡ lỗiBản năng đầu tiên của bạn nên là kiểm tra traceback. Nó chỉ ra chính xác dòng code nơi xảy ra sự cố. Tuy nhiên, thách thức thực sự là tìm ra lý do tại sao biến đó lại bằng không ngay từ đầu. Tôi thường thực hiện theo các bước sau:

  • Kiểm tra số chia: Thêm một câu lệnh print hoặc sử dụng trình gỡ lỗi (debugger) ngay trước khi tính toán. Nếu bạn thấy 0 hoặc 0.0, bạn đã tìm thấy mục tiêu.- Kiểm tra độ dài danh sách: Tính trung bình của một danh sách trống là một cái bẫy kinh điển. Nếu len(my_list) là 0, sum(my_list) / len(my_list) sẽ luôn thất bại.- Kiểm tra các bộ lọc: Đôi khi một df.filter() hoặc một list comprehension quá khắt khe. Nếu nó lọc bỏ mọi bản ghi, số chia của bạn sẽ trở thành số không.- Tìm kiếm dữ liệu bị thiếu: Trong các tệp CSV hoặc kết quả xuất SQL, các giá trị 'NULL' thường chuyển thành 0 tùy thuộc vào cách bạn tải dữ liệu.Dưới đây là một kịch bản lỗi điển hình:
def get_average_score(scores):
    # Nếu scores là [], len(scores) sẽ là 0
    return sum(scores) / len(scores)

data = []
print(get_average_score(data))

Trình thông dịch sẽ dừng lại và đưa ra lỗi này:

Traceback (most recent call last):
  File "script.py", line 5, in <module>
    print(get_average_score(data))
  File "script.py", line 3, in get_average_score
    return sum(scores) / len(scores)
ZeroDivisionError: division by zero

Các giải pháp khắc phục lỗi### 1. Kiểm tra điều kiện rõ ràng (If-Check)Kiểm tra số chia trước khi thực hiện phép chia là cách khắc phục đơn giản nhất. Nó giúp ý định của bạn trở nên rõ ràng với bất kỳ ai đọc mã nguồn. Cách này tốt nhất khi bạn có một giá trị 'dự phòng' hợp lý, chẳng hạn như 0.0%.

def get_average_score(scores):
    count = len(scores)
    if count == 0:
        return 0.0  # Trả về một giá trị mặc định hợp lý
    return sum(scores) / count

2. Sử dụng khối Try-ExceptCác lập trình viên Python thường tuân theo nguyên tắc 'EAFP': Thà xin lỗi còn hơn xin phép (Easier to Ask for Forgiveness than Permission). Hãy sử dụng khối try-except nếu bạn mong đợi phép chia hoạt động bình thường trong 99% trường hợp. Nó giữ cho luồng xử lý chính của mã nguồn sạch sẽ và xử lý trường hợp số không hiếm gặp như một ngoại lệ.

def calculate_ratio(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return 0.0

3. Xử lý số không trong PandasKhi xử lý các DataFrame lớn, một số không duy nhất trong một cột gồm 10.000 hàng có thể gây ra sự cố. Thay vì bị sập, Pandas thường trả về inf (vô cực). Để giữ cho dữ liệu của bạn sạch sẽ, hãy sử dụng .replace() để chuyển các số không thành NaN (Not a Number) trước khi chia.

import pandas as pd
import numpy as np

df = pd.DataFrame({'revenue': [1000, 2000, 3000], 'units_sold': [50, 0, 150]})

# Thay thế 0 bằng NaN để kết quả là NaN thay vì 'inf'
df['price_per_unit'] = df['revenue'] / df['units_sold'].replace(0, np.nan)

# Hoặc, sử dụng np.where cho một giá trị mặc định tùy chỉnh
df['price_per_unit'] = np.where(df['units_sold'] != 0, df['revenue'] / df['units_sold'], 0)

4. An toàn Vector hóa với NumPyNumPy cho phép bạn thực hiện các phép toán trên toàn bộ mảng. Bằng cách sử dụng np.divide với tham số where, bạn có thể bỏ qua hoàn toàn các số không và điền vào những vị trí đó một giá trị tùy chọn, chẳng hạn như 0 hoặc -1.

import numpy as np

a = np.array([10, 20, 30])
b = np.array([2, 0, 5])

# Chỉ chia ở những nơi b không bằng không; nếu không, sử dụng 0.0
result = np.divide(a, b, out=np.zeros_like(a, dtype=float), where=b!=0)

Các bước xác minhLuôn kiểm tra mã nguồn của bạn với các kịch bản 'trống'. Một cách khắc phục hoạt động tốt với các số dương vẫn có thể thất bại nếu nó gặp giá trị None hoặc giá trị âm sau này.

  • Kiểm tra với đầu vào trống: Truyền một danh sách trống [] vào các hàm của bạn để đảm bảo chúng không bị sập.- Kiểm tra tính nhất quán của kiểu dữ liệu: Nếu hàm của bạn thường trả về một số thực (như 5.5), hãy đảm bảo giá trị dự phòng khi có lỗi cũng là một số thực (0.0) thay vì một chuỗi ("N/A"). Việc trộn lẫn các kiểu dữ liệu có thể làm hỏng bước tiếp theo trong quy trình của bạn.- Tự động hóa với Pytest: Viết một trường hợp kiểm thử (test case) đơn giản để xử lý kịch bản số không.``` def test_division_logic(): assert calculate_ratio(10, 2) == 5.0 assert calculate_ratio(10, 0) == 0.0 print("Các bài kiểm tra đã vượt qua!")

test_division_logic()


## Bài học kinh nghiệm- **Làm sạch dữ liệu sớm:** Nếu bạn đang lấy dữ liệu từ một API bên ngoài, hãy khử trùng (sanitize) các số chia của bạn trước khi chúng đi vào logic tính toán.- **Chọn giá trị dự phòng cẩn thận:** Trả về `0` là điều phổ biến, nhưng `math.nan` thường tốt hơn trong khoa học dữ liệu vì nó đánh dấu rõ ràng dữ liệu đó là 'thiếu' hoặc 'không hợp lệ'.- **Độ chính xác rất quan trọng:** Phép toán số thực có thể lắt léo. Một giá trị có thể không chính xác là `0`, mà là một con số cực nhỏ như `1e-15`. Hãy sử dụng `math.isclose(val, 0, abs_tol=1e-9)` nếu bạn cần kiểm tra các giá trị 'gần bằng không' trong tính toán khoa học.

Related Error Notes