Cách sửa lỗi 'RuntimeError' khi dùng Multiprocessing trong Python trên Windows

beginner🐍 Python2026-07-10| Hệ điều hành Windows, Python 3.x, thư viện Multiprocessing

Error Message

RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase
#python#multiprocessing#windows#gỡ lỗi

Lỗi

Nếu bạn từng thử tăng tốc script Python trên Windows bằng module multiprocessing, có thể bạn đã gặp phải một trở ngại khó chịu. Thay vì code chạy nhanh hơn, bạn lại nhận được một loạt thông báo lỗi kết thúc bằng RuntimeError.

RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase.

This probably means that you are not using fork to start your child processes and you have forgotten to use the proper idiom in the main module:

    if __name__ == '__main__':
        freeze_support()
        ...

Tại sao lỗi này xảy ra

Sự cố này bắt nguồn từ sự khác biệt cơ bản trong cách các hệ điều hành xử lý các tiến trình mới. Linux và macOS thường sử dụng fork(). Phương thức này tạo ra một tiến trình con là bản sao y hệt của tiến trình cha, kế thừa mọi thứ đã có trong bộ nhớ.

Windows không có fork(). Thay vào đó, nó sử dụng một phương thức gọi là spawn. Khi bạn khởi chạy một tiến trình con trên Windows, Python sẽ khởi động một trình thông dịch hoàn toàn mới. Để đưa các hàm và biến của bạn vào instance mới này, Python phải import lại script của bạn từ đầu.

Đây chính là nơi vòng lặp logic xảy ra. Nếu đoạn code khởi chạy tiến trình con nằm ở "top level" (cấp cao nhất) của script, tiến trình con sẽ thực thi chính dòng lệnh đó khi nó import file. Điều này kích hoạt một tiến trình con thứ hai. Tiến trình đó lại kích hoạt tiến trình thứ ba. Chuỗi phản ứng đệ quy này tiếp tục cho đến khi mức sử dụng CPU tăng vọt và Python dừng script để ngăn hệ thống bị treo hoàn toàn.

Giải pháp: Sử dụng Main Guard

Cách khắc phục là một thay đổi cấu trúc đơn giản. Bạn phải bao bọc bất kỳ đoạn code nào khởi tạo tiến trình mới bên trong khối if __name__ == '__main__':. Việc kiểm tra điều kiện này đảm bảo code chỉ chạy khi bạn thực thi script trực tiếp, chứ không phải khi tiến trình con import nó.

Code sai (Kích hoạt vòng lặp)

import multiprocessing
import time

def worker():
    print("Tiến trình con đã bắt đầu")
    time.sleep(2)

# Dòng này chạy ngay lập tức khi import, gây ra đệ quy trên Windows
p = multiprocessing.Process(target=worker)
p.start()
p.join()

Code đúng (Cách khắc phục)

import multiprocessing
import time

def worker():
    print("Tiến trình con đã bắt đầu")
    time.sleep(2)

if __name__ == '__main__':
    # Khối này được bảo vệ và chỉ chạy trong tiến trình chính
    p = multiprocessing.Process(target=worker)
    p.start()
    p.join()
    print("Tiến trình con đã hoàn thành")

Xử lý Pool và Queue

Logic tương tự cũng áp dụng cho multiprocessing.Pool. Nếu bạn định nghĩa một pool gồm 4 worker bên ngoài main guard, Windows sẽ cố gắng tạo ra 4 tiến trình mới, mỗi tiến trình đó lại cố gắng tạo thêm 4 tiến trình nữa. Script của bạn sẽ bị crash gần như ngay lập tức.

import multiprocessing

def square(n):
    return n * n

if __name__ == '__main__':
    # Xác định rõ số lượng tiến trình thường sẽ an toàn hơn
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(square, [1, 2, 3, 4, 5])
        print(f"Kết quả: {results}")

Cách kiểm tra kết quả

Sau khi áp dụng guard, hãy kiểm tra script của bạn bằng ba phương pháp sau:

- **Thực thi qua Terminal:** Chạy `python your_script.py` trong PowerShell. Nó sẽ chạy đến khi hoàn tất mà không gặp lỗi bootstrapping.
- **Theo dõi Task Manager:** Mở Task Manager (Ctrl+Shift+Esc) khi script đang chạy. Nếu bạn đặt `processes=4`, bạn sẽ thấy chính xác năm instance `python.exe`: một tiến trình cha và bốn tiến trình con (worker).
- **Kiểm tra tiến trình ma:** Đảm bảo tất cả các tiến trình Python biến mất sau khi script kết thúc. Nếu chúng vẫn còn tồn tại, có thể bạn đang gặp vấn đề về `join()` hoặc đồng bộ hóa.

Thực hành tốt nhất cho người dùng Windows

Tôi khuyên bạn nên tuân theo các thói quen sau để giữ cho code chạy song song luôn ổn định:

- **Luôn sử dụng guard:** Hãy biến `if __name__ == '__main__':` thành thói quen mặc định cho mọi script. Nó ngăn chặn các tác dụng phụ ngoài ý muốn nếu bạn quyết định import các hàm của mình vào một dự án khác.
- **Giữ cho top level sạch sẽ:** Chỉ định nghĩa hằng số, class và hàm ở cấp cao nhất của file. Mọi "hành động" như in ấn hoặc khởi tạo pool nên nằm bên trong một hàm hoặc khối main guard.
- **Thêm freeze_support():** Nếu bạn định đóng gói script thành file `.exe` độc lập bằng PyInstaller, hãy gọi `multiprocessing.freeze_support()` ở ngay dòng đầu tiên bên trong khối main guard của bạn.

Related Error Notes