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

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


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

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

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

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

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

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

  • این کار به ۱۰۰ قاب در هر نخ و ۱۰۰ نخ (قابل تنظیم از طریق max_threads) محدود است.

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

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

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

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

همچنین ببینید

ماژول pdb

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

ماژول traceback

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

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

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

ردگیری‌های تمام نخ‌ها را در file برون‌ریزی کنید. اگر all_threads برابر با False باشد، فقط نخ فعلی برون‌ریزی می‌شود. max_threads سقف تعداد نخ‌های برون‌ریزی‌شده را تعیین می‌کند.

همچنین ببینید

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

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

تغییر یافته در نسخه‌ی 3.15: آرگومان کلیدواژه‌ای max_threads اضافه شد.

برون‌ریزی پشته‌ی 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, *, max_threads=100)

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

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

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

پارامتر max_threads سقف تعداد نخ‌های تخلیه‌شده هنگام بروز سیگنال مرگبار را تعیین می‌کند.

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

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

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

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

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

تغییر یافته در نسخه‌ی 3.15: آرگومان کلیدواژه‌ای max_threads اضافه شد.

faulthandler.disable()

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

faulthandler.is_enabled()

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

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

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

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

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

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

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

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

تغییر یافته در نسخه‌ی 3.15: آرگومان کلیدواژه‌ای max_threads اضافه شد.

faulthandler.cancel_dump_traceback_later()

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

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

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

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

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

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

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

تغییر یافته در نسخه‌ی 3.15: آرگومان کلیدواژه‌ای max_threads اضافه شد.

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.15/_ctypes.cpython-315d-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.15/_ctypes.cpython-315d-x86_64-linux-gnu.so", at +0x15a33 [0x77b7315e6a33]
  Binary file "/opt/python/build/lib.linux-x86_64-3.15/_ctypes.cpython-315d-x86_64-linux-gnu.so", at +0x164fa [0x77b7315e74fa]
  Binary file "/opt/python/build/lib.linux-x86_64-3.15/_ctypes.cpython-315d-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