298. Ручная отчётность об ошибках в main

Добавление полезной отчётности об ошибках эмуляции в main_only_background.py.

Урок 298 из 356 · tests/chapter_08_manual_main/test_298_manual_main_error_reporting.py

Файл для обновления

main_only_background.py

Зачем нужен этот шаг

main_only_background.py выполняет реальный ручной цикл ROM с pygame. Когда реальное выполнение ROM сталкивается с отсутствующим поведением эмулятора, пользователю нужен контекст до трассировки Python.

Без контекста ошибка может выглядеть просто как

ValueError: Unsupported CPU bus read: 4020

С контекстом main_only_background.py также должен выводить полезное состояние эмулятора:

Emulation Error:
    type=ValueError
    message=Unsupported CPU bus read: 4020
    pc=$812A
    ppu_frame=123
    ppu_scanline=241
    ppu_cycle=10

Это не заменяет трассировку. Исходное исключение по-прежнему должно быть повторно возбуждено, чтобы разработчики могли отлаживать как обычно.

Пример предполагаемой реализации

def print_emulation_error(error: Exception, console: Console) -> None:
    print("

Emulation Error:")

    print(f"    type={type(error).__name__}")
    print(f"    message={error}")
    print(f"    pc=${console.cpu.pc:04X}")
    print(f"    ppu_frame={console.ppu.frame}")
    print(f"    ppu_scanline={console.ppu.scanline}")
    print(f"    ppu_cycle={console.ppu.cycle}")


def main() -> None:
    ...

    pygame.init()
    try:
        window = pygame.display.set_mode(...)

        running = True
        while running:
            ...

            executed = console.step_until_next_frame()
            framebuffer = console.render_background_framebuffer()
            draw_framebuffer(window, framebuffer, SCALE)
            pygame.display.flip()

    except KeyboardInterrupt:
        print("

Stopped by user.")

    except Exception as error:
        print_emulation_error(error, console)
        raise
    finally:
        pygame.quit()

Почему KeyboardInterrupt перехватывается отдельно? Ctrl+C — это намеренная остановка пользователем, а не сбой эмулятора. Должно выводиться дружелюбное сообщение об остановке, а не отчёт об ошибке эмуляции.

Почему неожиданные исключения повторно возбуждаются? Отчёт об ошибке даёт контекст эмулятора, но трассировка всё равно важна. Повторное возбуждение сохраняет исходный сбой видимым для отладки.

Вне рамок этого шага

  • изменение диагностики опкодов CPU
  • перехват и скрытие всех ошибок
  • запись логов в файлы
  • вызов main() из pytest

Запустить этот урок

uv run pytest tests/chapter_08_manual_main/test_298_manual_main_error_reporting.py -v