PyCrashReport
PyCrashReport is a pure Python 3 library designed for parsing and analyzing Apple's crash reports, distilling them into a clearer view by focusing on essential debugging data. It supports user-mode and kernel-mode crash reports, providing basic metadata for other types. The library is actively maintained, with frequent minor updates and a recent major version release (v2.0.0).
Common errors
-
FileNotFoundError: [Errno 2] No such file or directory: 'non_existent_report.ips'
cause The path provided to the `CrashReport` constructor (or CLI) for the crash report file does not exist.fixVerify that the file path for the crash report is correct and that the file exists at that location. Use an absolute path or ensure the script is run from the correct directory. -
Error parsing crash report: Crash report file is not valid
cause The input content provided to `CrashReport` is not a valid Apple crash report format, or it's severely malformed. PyCrashReport expects a specific structure for accurate parsing.fixEnsure the input is a genuine Apple crash report (e.g., an .ips file) and not corrupted. The library may only extract basic metadata for unsupported or severely malformed types. Review the content for standard Apple crash report headers and sections. -
AttributeError: 'CrashReport' object has no attribute 'some_missing_attribute'
cause Attempting to access an attribute (e.g., `report.some_missing_attribute`) that does not exist in the parsed `CrashReport` object. This can happen if the crash report itself lacks that specific data, or if the attribute name is incorrect.fixConsult the PyCrashReport documentation or the object's `__dict__` for available attributes. Check the original crash report content; if the data isn't present in the report, the corresponding attribute might be `None` or not exist.
Warnings
- breaking The v2.0.0 release includes 'Update project standards' and a major version bump from 1.x. While specific breaking API changes aren't explicitly detailed in the release notes, users upgrading from 1.x should review the full changelog on GitHub for potential incompatibilities in API or behavior, especially for custom integrations.
- gotcha Versions prior to v1.2.7 contained a bug that could lead to 'double-parsing of integer registers', resulting in incorrect register values in the parsed crash reports. This could lead to misdiagnosis of crash causes.
- breaking The command-line script name was changed from a previous name (implicitly 'pycrash' or similar) to `pycrashreport` in version 1.2.1. Users relying on the CLI utility with older script names will experience 'command not found' errors.
Install
-
pip install pycrashreport
Imports
- CrashReport
from pycrashreport.crash_report import CrashReport
Quickstart
import os
from pycrashreport.crash_report import CrashReport
# Simulate a crash report content (replace with actual file reading)
crash_report_content = """
Incident Identifier: 1234ABCD-ABCD-ABCD-ABCD-1234ABCDABCD
CrashReporter Key: 0123456789abcdef0123456789abcdef01234567
Hardware Model: iPhone13,4
Process: MyApp [1234]
Path: /private/var/containers/Bundle/Application/APP_UUID/MyApp.app/MyApp
Identifier: com.example.MyApp
Version: 1.0 (1)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time: 2026-04-16 10:00:00.000 +0000
OS Version: iOS 17.4 (21E236)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [1234]
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x180000000 0x180000000 + 0x21c4
1 MyApp 0x100000000 main + 0 (main.m:16)
2 dyld 0x102000000 start + 0
Binary Images:
0x100000000 - 0x100003fff MyApp arm64e <UUID> /private/var/containers/Bundle/Application/APP_UUID/MyApp.app/MyApp
0x180000000 - 0x18001ffff libsystem_kernel.dylib arm64e <UUID> /usr/lib/system/libsystem_kernel.dylib
0x102000000 - 0x102033fff dyld arm64e <UUID> /usr/lib/dyld
"""
try:
# It's common to pass the raw content or a file-like object
# For a real file, you would use: with open('path/to/report.ips', 'r') as f: report = CrashReport(f.read())
report = CrashReport(crash_report_content)
print(f"Incident Identifier: {report.incident_identifier}")
print(f"Process Name: {report.process_name}")
print(f"Process ID: {report.process_id}")
print(f"OS Version: {report.os_version}")
print(f"Exception Type: {report.exception_type}")
print(f"Crashed Thread: {report.crashed_thread_id}")
if report.crashed_thread and report.crashed_thread.frames:
print("\nCrashed Thread Backtrace:")
for frame in report.crashed_thread.frames:
print(f" {frame.image_name} {frame.address} {frame.symbol_name if frame.symbol_name else ''}")
except Exception as e:
print(f"Error parsing crash report: {e}")