faulthandler --- برون‌ریزی ردگیری پشته پایتون

اضافه شده در نسخه‌ی 3.3.


این ماژول شامل توابعی برای برون‌ریزی از ردگیری‌های پشته‌ی پایتون به‌صورت صریح، در صورت بروز خطا، پس از پایان مهلت، یا هنگام دریافت سیگنال کاربر است. faulthandler.enable() را فراخوانی کنید تا هندلرهای خطا برای سیگنال‌های SIGSEGV، SIGFPE، SIGABRT، SIGBUS و SIGILL نصب شوند. همچنین می‌توانید آن‌ها را در زمان راه‌اندازی با تنظیم متغیر محیطی PYTHONFAULTHANDLER یا با استفاده از گزینه‌ی خط فرمان -X faulthandler فعال کنید.

هندلر خطا با هندلرهای خطای سیستمی مانند Apport یا هندلر خطای ویندوز سازگار است. در صورتی که تابع sigaltstack() در دسترس باشد، این ماژول برای هندلرهای سیگنال از یک پشته جایگزین استفاده می‌کند. این امر به آن امکان می‌دهد که ردگیری پشته را حتی در صورت سرریز پشته نیز برون‌ریزی کند.

هندلر خطا (fault handler) در موارد فاجعه‌بار فراخوانی می‌شود و بنابراین تنها می‌تواند از توابع ایمن در برابر سیگنال (signal-safe) استفاده کند (برای مثال، نمی‌تواند حافظه‌ای را در هیپ تخصیص دهد). به دلیل این محدودیت، برون‌ریزی ردگیری پشته در مقایسه با ردگیری‌های پشته‌ی معمول پایتون حداقلی است:

  • فقط ASCII پشتیبانی می‌شود. هنگام کدگذاری از هندلر خطای backslashreplace استفاده می‌شود.

  • هر رشته به ۵۰۰ نویسه محدود است.

  • فقط نام پرونده، نام تابع و شماره‌ی خط نمایش داده می‌شوند. (بدون کد منبع)

  • آن به ۱۰۰ فریم و ۱۰۰ نخ محدود شده است.

  • ترتیب معکوس است: جدیدترین فراخوانی ابتدا نمایش داده می‌شود.

به‌طور پیش‌فرض، ردگیری پشته پایتون در sys.stderr نوشته می‌شود. برای مشاهده ردگیری‌های پشته، برنامه‌ها باید در پایانه اجرا شوند. به‌عنوان جایگزین، می‌توان یک پرونده گزارش را به faulthandler.enable() پاس داد.

این ماژول به زبان C پیاده‌سازی شده است، بنابراین در صورت بروز فروپاشی یا هنگامی که پایتون در بن‌بست (deadlock) باشد، می‌توان ردگیری‌های پشته را برون‌ریزی کرد.

حالت توسعه پایتون در زمان راه‌اندازی پایتون، faulthandler.enable() را فراخوانی می‌کند.

همچنین ملاحظه نمائید

ماژول pdb

اشکال‌زدای تعاملی کد منبع برای برنامه‌های پایتون.

ماژول traceback

رابط استاندارد برای استخراج، قالب‌بندی و چاپ ردگیری‌های پشته در برنامه‌های پایتون.

برون‌ریزی ردگیری پشته

faulthandler.dump_traceback(file=sys.stderr, all_threads=True)

ردگیری‌های پشته‌ی همه‌ی نخ‌ها را در file بنویسید. اگر all_threads False باشد، فقط ردگیری پشته‌ی نخ جاری را بنویسید.

همچنین ملاحظه نمائید

traceback.print_tb()، که می‌تواند برای چاپ یک شیء ردگیری پشته استفاده شود.

تغییر یافته در نسخه‌ی 3.5: پشتیبانی از ارسال توصیف‌گر پرونده به این تابع افزوده شد.

برون‌ریزی پشته‌ی C

اضافه شده در نسخه‌ی 3.14.

faulthandler.dump_c_stack(file=sys.stderr)

برون‌ریزی ردگیری پشته‌ی C نخ جاری را در file بگیرید.

اگر ساخت پایتون از آن پشتیبانی نکند یا سیستم‌عامل ردگیری پشته را فراهم نکند، این مورد به‌جای پشته‌ی برون‌ریزی‌شده‌ی C، خطایی را چاپ می‌کند.

سازگاری پشته‌ی C

اگر سیستم از backtrace(3) یا dladdr1(3) در سطح C پشتیبانی نکند، برون‌ریزی پشته‌ی C کار نخواهد کرد. به‌جای پشته، خطایی چاپ خواهد شد.

علاوه بر این، برخی کامپایلرها از پیاده‌سازی CPython برای برون‌ریزی پشته‌های C (stack dumps) پشتیبانی نمی‌کنند. در نتیجه، حتی اگر سیستم‌عامل از تخلیه پشته‌ها پشتیبانی کند، ممکن است به‌جای پشته، خطای متفاوتی چاپ شود.

توجه

برون‌ریزی پشته‌های C می‌تواند بسته به سطح DWARF پرونده‌های دودویی موجود در پشته‌ی فراخوانی، به‌هر اندازه‌ای کند باشد.

وضعیت هندلر خطا

faulthandler.enable(file=sys.stderr, all_threads=True, c_stack=True)

فعال‌سازی هندلر خطا : نصب هندلرهایی برای سیگنال‌های SIGSEGV، SIGFPE، SIGABRT، SIGBUS و SIGILL برای خروجی گرفتن از ردگیری پشته پایتون. اگر all_threads برابر True باشد، برای هر نخ در حال اجرا ردگیری پشته تولید می‌شود. در غیر این صورت، فقط ردگیری پشته نخ جاری خروجی گرفته می‌شود.

file باید تا پیش از غیرفعال‌شدن هندلر خطا باز بماند: مشکل توصیف‌گرهای پرونده را ببینید.

اگر c_stack برابر True باشد، ردگیری پشته C پس از ردگیری پشته پایتون چاپ می‌شود، مگر آنکه سیستم از آن پشتیبانی نکند. برای اطلاعات بیشتر درباره سازگاری، dump_c_stack() را ببینید.

تغییر یافته در نسخه‌ی 3.5: پشتیبانی از ارسال توصیف‌گر پرونده به این تابع افزوده شد.

تغییر یافته در نسخه‌ی 3.6: در ویندوز، یک هندلر برای استثنای ویندوز نیز نصب می‌شود.

تغییر یافته در نسخه‌ی 3.10: اگر all_threads true باشد، اکنون در برون‌ریزی ذکر می‌شود که آیا یک جمع‌آوری زباله‌روبی در حال اجرا است یا خیر.

تغییر یافته در نسخه‌ی 3.14: در صورت غیرفعال بودن GIL، فقط نخ جاری dump می‌شود تا از خطر رقابت‌های داده‌ای جلوگیری شود.

تغییر یافته در نسخه‌ی 3.14: برون‌ریزی اکنون در صورتی که c_stack برابر true باشد، ردگیری پشته‌ی C را نمایش می‌دهد.

faulthandler.disable()

غیرفعال‌سازی هندلر خطا : حذف مدیرهای سیگنال نصب‌شده توسط enable().

faulthandler.is_enabled()

بررسی کنید که آیا هندلر خطا فعال است یا خیر.

برون‌ریزی ردگیری‌های پشته پس از پایان مهلت

faulthandler.dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False)

ردگیری‌های پشته‌ی تمام نخ‌ها را پس از گذشت timeout ثانیه، یا هر timeout ثانیه در صورتی که repeat برابر True باشد، برون‌ریزی می‌کند. اگر exit برابر True باشد، پس از برون‌ریزی ردگیری‌های پشته، _exit() را با status=1 فراخوانی می‌کند. (توجه: _exit() فرآیند را بلافاصله خاتمه می‌دهد، به این معنا که هیچ‌گونه پاک‌سازی مانند برون‌ریزی بافرهای پرونده انجام نمی‌دهد.) اگر این تابع دو بار فراخوانی شود، فراخوانی جدید پارامترهای پیشین را جایگزین می‌کند و مهلت زمانی را بازنشانی می‌کند. زمان‌سنج دقتی کمتر از یک ثانیه دارد.

file باید تا زمانی که ردگیری پشته برون‌ریزی شود یا cancel_dump_traceback_later() فراخوانی شود، باز بماند: مسئله‌ی توصیف‌گرهای پرونده را ببینید.

این تابع با استفاده از یک نخ دیده‌بان (watchdog thread) پیاده‌سازی شده است.

تغییر یافته در نسخه‌ی 3.5: پشتیبانی از ارسال توصیف‌گر پرونده به این تابع افزوده شد.

تغییر یافته در نسخه‌ی 3.7: این تابع اکنون همیشه در دسترس است.

faulthandler.cancel_dump_traceback_later()

آخرین فراخوانی dump_traceback_later() را لغو می‌کند.

برون‌ریزی ردگیری پشته در سیگنال کاربر

faulthandler.register(signum, file=sys.stderr, all_threads=True, chain=False)

ثبت یک سیگنال کاربر: یک هندلر برای سیگنال signum نصب می‌شود تا ردگیری پشته همه نخ‌ها، یا نخ جاری اگر all_threads برابر False باشد، در file نوشته شود. اگر chain برابر True باشد، هندلر پیشین فراخوانی می‌شود.

file باید تا زمانی که سیگنال توسط unregister() از ثبت خارج شود، باز بماند: به مشکل توصیف‌گرهای پرونده مراجعه کنید.

در ویندوز در دسترس نیست.

تغییر یافته در نسخه‌ی 3.5: پشتیبانی از ارسال توصیف‌گر پرونده به این تابع افزوده شد.

faulthandler.unregister(signum)

لغو ثبت یک سیگنال کاربر: حذف هندلر سیگنال signum نصب‌شده توسط register(). اگر سیگنال ثبت‌شده باشد، True و در غیر این صورت False برمی‌گرداند.

در ویندوز در دسترس نیست.

مشکل مربوط به توصیف‌گرهای پرونده

enable()، dump_traceback_later() و register() توصیف‌گر فایلِ آرگومان file خود را نگه می‌دارند. اگر پرونده بسته شود و توصیف‌گر پرونده آن توسط یک پرونده جدید دوباره استفاده شود، یا اگر از os.dup2() برای جایگزینی توصیف‌گر پرونده استفاده شود، ردگیری پشته در یک پرونده دیگر نوشته خواهد شد. هر بار که پرونده جایگزین می‌شود، این توابع را دوباره فراخوانی کنید.

مثال

نمونه‌ای از خطای قطعه‌بندی (segmentation fault) در لینوکس، با فعال‌سازی مدیر خطا و بدون فعال‌سازی آن:

$ python -c "import ctypes; ctypes.string_at(0)"
Segmentation fault

$ python -q -X faulthandler
>>> import ctypes
>>> ctypes.string_at(0)
Fatal Python error: Segmentation fault

Current thread 0x00007fb899f39700 (most recent call first):
  File "/opt/python/Lib/ctypes/__init__.py", line 486 in string_at
  File "<stdin>", line 1 in <module>

Current thread's C stack trace (most recent call first):
  Binary file "/opt/python/python", at _Py_DumpStack+0x42 [0x5b27f7d7147e]
  Binary file "/opt/python/python", at +0x32dcbd [0x5b27f7d85cbd]
  Binary file "/opt/python/python", at +0x32df8a [0x5b27f7d85f8a]
  Binary file "/usr/lib/libc.so.6", at +0x3def0 [0x77b73226bef0]
  Binary file "/usr/lib/libc.so.6", at +0x17ef9c [0x77b7323acf9c]
  Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0xcdf6 [0x77b7315dddf6]
  Binary file "/usr/lib/libffi.so.8", at +0x7976 [0x77b73158f976]
  Binary file "/usr/lib/libffi.so.8", at +0x413c [0x77b73158c13c]
  Binary file "/usr/lib/libffi.so.8", at ffi_call+0x12e [0x77b73158ef0e]
  Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0x15a33 [0x77b7315e6a33]
  Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0x164fa [0x77b7315e74fa]
  Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0xc624 [0x77b7315dd624]
  Binary file "/opt/python/python", at _PyObject_MakeTpCall+0xce [0x5b27f7b73883]
  Binary file "/opt/python/python", at +0x11bab6 [0x5b27f7b73ab6]
  Binary file "/opt/python/python", at PyObject_Vectorcall+0x23 [0x5b27f7b73b04]
  Binary file "/opt/python/python", at _PyEval_EvalFrameDefault+0x490c [0x5b27f7cbb302]
  Binary file "/opt/python/python", at +0x2818e6 [0x5b27f7cd98e6]
  Binary file "/opt/python/python", at +0x281aab [0x5b27f7cd9aab]
  Binary file "/opt/python/python", at PyEval_EvalCode+0xc5 [0x5b27f7cd9ba3]
  Binary file "/opt/python/python", at +0x255957 [0x5b27f7cad957]
  Binary file "/opt/python/python", at +0x255ab4 [0x5b27f7cadab4]
  Binary file "/opt/python/python", at _PyEval_EvalFrameDefault+0x6c3e [0x5b27f7cbd634]
  Binary file "/opt/python/python", at +0x2818e6 [0x5b27f7cd98e6]
  Binary file "/opt/python/python", at +0x281aab [0x5b27f7cd9aab]
  Binary file "/opt/python/python", at +0x11b6e1 [0x5b27f7b736e1]
  Binary file "/opt/python/python", at +0x11d348 [0x5b27f7b75348]
  Binary file "/opt/python/python", at +0x11d626 [0x5b27f7b75626]
  Binary file "/opt/python/python", at PyObject_Call+0x20 [0x5b27f7b7565e]
  Binary file "/opt/python/python", at +0x32a67a [0x5b27f7d8267a]
  Binary file "/opt/python/python", at +0x32a7f8 [0x5b27f7d827f8]
  Binary file "/opt/python/python", at +0x32ac1b [0x5b27f7d82c1b]
  Binary file "/opt/python/python", at Py_RunMain+0x31 [0x5b27f7d82ebe]
  <truncated rest of calls>
Segmentation fault