[Các vấn đề của Python 3.10] Thay đổi nội bộ làm lộ lỗi (PEP 626 & bạn bè)

By JoeVu, at: 15:01 Ngày 06 tháng 8 năm 2025

Thời gian đọc ước tính: __READING_TIME__ minutes

[Python 3.10 issues] Internal Changes Exposed Bugs (PEP 626 & friends)
[Python 3.10 issues] Internal Changes Exposed Bugs (PEP 626 & friends)

Các triệu chứng có thể gặp

 

  • Trình gỡ lỗi/công cụ phân tích hiệu suất/công cụ theo dõi hoạt động bất thường (điểm ngắt bỏ lỡ dòng, độ bao phủ không khớp).
     

  • Các công cụ dựa vào độ lệch bytecodes bị lỗi (ví dụ: giả định về frame.f_lasti).
     

  • Các công cụ tùy chỉnh theo dõi, kiểm tra frame/bytecode trở nên không chính xác.

 

Tại sao điều này xảy ra

 

Python 3.10 đã áp dụng bảng số dòng chính xác (PEP 626), thay đổi cách trình thông dịch ánh xạ bytecode tới các dòng mã nguồn. Như một phần của điều này:

 

  • frame.f_lasti thực tế trở thành độ lệch chỉ thị thay vì độ lệch byte thô (trình thông dịch đã chuyển sang wordcode trước đó; 3.10 đã làm chặt ngữ nghĩa). Xem Có gì mới trong 3.10 → Tracebacks & số dòng và tài liệu đối tượng frame.
     

  • Bảng số dòng hiện đã chính xác hơn cho các ngoại lệ và theo dõi, điều này rất tốt cho người dùng, nhưng làm hỏng các công cụ phụ thuộc vào các hành vi cũ, không chính thức.

 

Các mẫu sửa lỗi / di chuyển

 

1) Không dựa vào chi tiết nội bộ của bytecode. Sử dụng các API được hỗ trợ.

 

  • Ưu tiên mô-đun dis để suy luận về các chỉ thị/độ lệch thay vì mã hóa cứng độ lệch.
     

  • Đối với các vị trí mã nguồn, hãy dựa vào các thuộc tính frame.f_lineno và đối tượng mã (co_filename, co_firstlineno, co_positions() trong 3.11+) thay vì tự giải mã các chi tiết nội bộ. Xem inspect.

 

2) Cập nhật logic theo dõi/gỡ lỗi cho ngữ nghĩa PEP 626.

 

  • Nếu bạn triển khai sys.settrace/sys.setprofile, hãy mong đợi nhiều sự kiện theo dõi hơn và nhảy dòng chính xác hơn. Xem lại tài liệu hàm gọi theo dõi và điều chỉnh bộ lọc để bạn không đếm thừa độ bao phủ hoặc bỏ lỡ các nhánh.

 

3) Sử dụng các thư viện cấp cao hơn khi có thể.

 

  • Đối với việc viết lại/phân tích mã, hãy ưu tiên ast/LibCST hơn là can thiệp vào bytecode. Bytecode không phải là một giao diện ổn định; AST mới là vậy.

 

4) Biên dịch lại & kiểm thử lại các tiện ích mở rộng C và bất kỳ tích hợp frame/bytecode nào.

 

  • Nếu một tiện ích mở rộng C chạm vào các chi tiết nội bộ của frame hoặc đối tượng mã, hãy biên dịch lại trên 3.10 và kiểm tra các thay đổi API C của 3.10.

 

 

Ví dụ: công cụ theo dõi giả định độ lệch byte

 

# Cũ: so sánh f_lasti thô (được coi như độ lệch byte)
def trace(frame, event, arg):
    if frame.f_lasti in SOME_BYTE_OFFSETS:   # dễ vỡ
        ...
    return trace


# Mới: sử dụng dis để ánh xạ độ lệch chỉ thị một cách mạnh mẽ
import dis
def trace(frame, event, arg):
    code = frame.f_code
    instrs = list(dis.get_instructions(code))
    # khớp theo (offset, starts_line) hoặc theo mẫu opname/name thay vì số thô
    ...
    return trace

 

Làm thế nào để tránh sự cố lần tới

 

  • Coi bytecode là không ổn định. Nếu bạn nhất thiết phải kiểm tra nó, hãy sử dụng dis và giữ cho logic của bạn có khả năng chống chịu với sự thay đổi độ lệch.
     

  • Thêm CI trên các phiên bản Python mới sớm (alpha/beta) để các công cụ theo dõi/độ bao phủ hiển thị các thay đổi trước khi phát hành chính thức (GA).
     

  • Ưu tiên tích hợp ở cấp AST/mã nguồn để có khả năng tương thích trên các phiên bản.

 

Tag list:

Theo dõi

Theo dõi bản tin của chúng tôi và không bao giờ bỏ lỡ những tin tức mới nhất.