bdb --- چارچوب اشکال‌زدا

کد منبع: Lib/bdb.py


ماژول bdb عملکردهای پایه‌ی اشکال‌زدا را بر عهده دارد، مانند تنظیم نقاط توقف یا مدیریت اجرا از طریق اشکال‌زدا.

استثنای زیر تعریف شده است:

exception bdb.BdbQuit

استثنایی که توسط کلاس Bdb برای خروج از اشکال‌زدا پرتاب می‌شود.

ماژول bdb همچنین دو کلاس تعریف می‌کند:

class bdb.Breakpoint(self, file, line, temporary=False, cond=None, funcname=None)

این کلاس نقاط توقف موقت، تعداد نادیده‌گرفتن، غیرفعال‌سازی و فعال‌سازی مجدد، و شرطی‌ها را پیاده‌سازی می‌کند.

نقاط شکست بر اساس شماره از طریق فهرستی به نام bpbynumber و بر اساس جفت‌های (file, line) از طریق bplist اندیس‌دهی شده‌اند. مورد اول به یک نمونه از کلاس Breakpoint اشاره می‌کند. مورد دوم به فهرستی از چنین نمونه‌هایی اشاره می‌کند، زیرا ممکن است بیش از یک نقطه شکست در هر خط وجود داشته باشد.

هنگام ایجاد یک نقطه توقف، file name مرتبط با آن باید به‌صورت کانونیکال باشد. اگر funcname تعریف شده باشد، با اجرای اولین خط آن تابع، یک hit برای نقطه توقف شمارش می‌شود. نقطه توقف conditional همیشه یک hit را می‌شمارد.

نمونه‌های Breakpoint متدهای زیر را دارند:

deleteMe()

نقطه توقف را از فهرست مرتبط با پرونده/خط حذف می‌کند. اگر آخرین نقطه توقف در آن موقعیت باشد، آیتم مربوط به پرونده/خط را نیز حذف می‌کند.

enable()

نقطه توقف را به‌عنوان فعال علامت‌گذاری کنید.

disable()

نقطه توقف را به‌عنوان غیرفعال علامت‌گذاری می‌کند.

bpformat()

رشته‌ای حاوی همه اطلاعات درباره نقطه توقف (breakpoint) با قالب‌بندی مناسب برمی‌گرداند:

  • شماره‌ی نقطه‌ی توقف.

  • وضعیت موقت (حذف یا نگهداری).

  • موقعیت پرونده/خط.

  • شرط توقف.

  • تعداد دفعاتی که باید نادیده گرفته شود.

  • تعداد دفعات برخورد.

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

bpprint(out=None)

خروجی bpformat() را در پرونده out چاپ می‌کند، یا اگر out None باشد، در خروجی استاندارد.

نمونه‌های Breakpoint دارای ویژگی‌های زیر هستند:

file

نام فایلِ Breakpoint.

line

شماره‌ی خط Breakpoint در file.

temporary

True اگر یک Breakpoint در (file, line) موقت باشد.

cond

شرط برای ارزیابی یک Breakpoint در (file, line).

funcname

نام تابعی که تعیین می‌کند آیا یک Breakpoint هنگام ورود به تابع فعال می‌شود یا خیر.

enabled

اگر Breakpoint فعال باشد، True است.

bpbynumber

اندیس عددی برای یک نمونه از Breakpoint.

bplist

دیکشنری از نمونه‌های Breakpoint که با تاپل‌های (file، line) اندیس‌گذاری شده است.

ignore

تعداد دفعاتی که باید یک Breakpoint نادیده گرفته شود.

hits

تعداد دفعاتی که به یک Breakpoint رسیده است.

class bdb.Bdb(skip=None, backend='settrace')

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

این کلاس جزئیات سازوکار ردگیری را بر عهده می‌گیرد؛ یک کلاس مشتق باید تعامل با کاربر را پیاده‌سازی کند. کلاس اشکال‌زدای استاندارد (pdb.Pdb) نمونه‌ای است.

آرگومان skip، در صورت ارائه‌شدن، باید پیمایش‌پذیری از الگوهای نام ماژول به‌سبک glob باشد. اشکال‌زدا وارد فریم‌هایی که از ماژولی منطبق با یکی از این الگوها سرچشمه می‌گیرند، نمی‌شود. اینکه یک فریم سرچشمه‌گرفته از یک ماژول معین در نظر گرفته شود، با __name__ در فضای نام سراسری فریم تعیین می‌شود.

آرگومان backend مشخص می‌کند که کدام بک‌اند برای Bdb استفاده شود. این آرگومان می‌تواند 'settrace' یا 'monitoring' باشد. 'settrace' از sys.settrace() استفاده می‌کند که بهترین سازگاری رو به عقب را دارد. بک‌اند 'monitoring' از sys.monitoring جدیدی استفاده می‌کند که در پایتون 3.12 معرفی شده است و می‌تواند بسیار کارآمدتر باشد، زیرا می‌تواند رویدادهای استفاده‌نشده را غیرفعال کند. ما در تلاشیم رابط‌های دقیقاً یکسانی را برای هر دو بک‌اند حفظ کنیم، اما تفاوت‌هایی وجود دارد. توسعه‌دهندگان اشکال‌زدا تشویق می‌شوند برای دستیابی به عملکرد بهتر از بک‌اند 'monitoring' استفاده کنند.

تغییر یافته در نسخه‌ی 3.1: پارامتر skip افزوده شد.

تغییر یافته در نسخه‌ی 3.14: پارامتر backend افزوده شد.

متدهای زیرِ Bdb معمولاً نیازی به بازنویسی ندارند.

canonic(filename)

صورت کانونیکال filename را برمی‌گرداند.

برای نام پرونده‌های واقعی، صورت کانونیکال یک مسیر مطلق است که به سیستم‌عامل وابسته است و نرمال‌شده از نظر بزرگی و کوچکی حروف است. یک نام پرونده دارای علامت‌های زاویه‌ای، مانند "<stdin>" که در حالت تعاملی تولید می‌شود، بدون تغییر برگردانده می‌شود.

start_trace(self)

ردگیری را شروع می‌کند. برای بک‌اند 'settrace'، این متد معادل sys.settrace(self.trace_dispatch) است

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

stop_trace(self)

ردگیری را متوقف می‌کند. برای بک‌اند 'settrace'، این متد معادل sys.settrace(None) است

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

reset()

ویژگی‌های botframe، stopframe، returnframe و quitting را با مقادیر آماده برای شروع اشکال‌زدایی تنظیم کنید.

trace_dispatch(frame, event, arg)

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

پیاده‌سازی پیش‌فرض بسته به نوع رویدادی که به‌صورت یک رشته ارسال می‌شود و قرار است اجرا شود، تصمیم می‌گیرد که چگونه یک فریم را اعزام (dispatch) کند. event می‌تواند یکی از موارد زیر باشد:

  • "line": خط جدیدی از کد در شرف اجرا است.

  • "call": یک تابع در آستانه‌ی فراخوانی است، یا به بلوک کد دیگری وارد شده است.

  • "return": یک تابع یا بلوک کد دیگر در آستانه بازگشت است.

  • "exception": یک استثنا رخ داده است.

  • "c_call": یک تابع C در آستانه فراخوانی است.

  • "c_return": یک تابع C بازگشته است.

  • "c_exception": یک تابع C استثنایی را پرتاب کرده است.

برای رویدادهای پایتون، توابع تخصصی (در زیر ببینید) فراخوانی می‌شوند. برای رویدادهای C، هیچ اقدامی انجام نمی‌شود.

پارامتر arg به رویداد قبلی بستگی دارد.

برای اطلاعات بیشتر درباره تابع ردگیری، مستندات sys.settrace() را ببینید. برای اطلاعات بیشتر درباره اشیای کد و فریم، به سلسله‌مراتب انواع استاندارد مراجعه کنید.

dispatch_line(frame)

اگر اشکال‌زدا باید در خط فعلی متوقف شود، متد user_line() را فراخوانی کنید (که باید در زیرکلاس‌ها بازنویسی شود). اگر پرچم quitting تنظیم شده باشد (که می‌توان آن را از user_line() تنظیم کرد)، استثنای BdbQuit را پرتاب کنید. ارجاعی به متد trace_dispatch() برای ردگیری بیشتر در آن محدوده بازگشت دهید.

dispatch_call(frame, arg)

اگر اشکال‌زدا باید در این فراخوانی تابع متوقف شود، متد user_call() را فراخوانی کنید (که باید در زیرکلاس‌ها بازنویسی شود). اگر پرچم quitting تنظیم شده باشد (که می‌توان آن را از user_call() تنظیم کرد)، استثنای BdbQuit را پرتاب کنید. مرجعی به متد trace_dispatch() برای ردگیری بیشتر در آن محدوده برگردانید.

dispatch_return(frame, arg)

اگر اشکال‌زدا باید هنگام بازگشت این تابع متوقف شود، متد user_return() را فراخوانی کنید (که باید در زیرکلاس‌ها بازنویسی شود). اگر پرچم quitting تنظیم شده باشد (که می‌توان آن را از user_return() تنظیم کرد)، استثنای BdbQuit را پرتاب کنید. ارجاعی به متد trace_dispatch() برای ردگیری بیشتر در آن محدوده برگردانید.

dispatch_exception(frame, arg)

اگر اشکال‌زدا باید در این استثنا متوقف شود، متد user_exception() را فراخوانی می‌کند (که باید در زیرکلاس‌ها بازنویسی شود). اگر پرچم quitting تنظیم‌شده باشد (که می‌توان آن را از user_exception() تنظیم کرد)، استثنای BdbQuit را پرتاب می‌کند. برای ردگیری بیشتر در آن محدوده، ارجاعی به متد trace_dispatch() بازمی‌گرداند.

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

is_skipped_module(module_name)

اگر module_name با هر الگوی رد کردن (skip pattern) مطابقت داشته باشد، True را برمی‌گرداند.

stop_here(frame)

اگر frame در پشته پایین‌تر از فریم آغازین باشد، True را برمی‌گرداند.

break_here(frame)

اگر برای این خط یک نقطه توقف مؤثر وجود داشته باشد، True را برمی‌گرداند.

بررسی کنید که آیا نقطه‌توقفی برای خط یا تابع وجود دارد و فعال است یا خیر. نقطه‌توقف‌های موقت را بر اساس اطلاعات effective() حذف کنید.

break_anywhere(frame)

اگر نقطه توقفی برای نام پرونده frame وجود داشته باشد، True را برمی‌گرداند.

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

user_call(frame, argument_list)

اگر ممکن باشد یک نقطه توقف درون تابع فراخوانی‌شده باعث توقف شود، از dispatch_call() فراخوانی می‌شود.

argument_list دیگر استفاده نمی‌شود و همیشه None خواهد بود. این آرگومان برای سازگاری با نسخه‌های پیشین نگه داشته شده است.

user_line(frame)

از dispatch_line() فراخوانی می‌شود، هرگاه stop_here() یا break_here() مقدار True را برگرداند.

user_return(frame, return_value)

از dispatch_return() فراخوانی می‌شود، هنگامی که stop_here() مقدار True را برمی‌گرداند.

user_exception(frame, exc_info)

از dispatch_exception() فراخوانی می‌شود، هنگامی که stop_here() مقدار True را برمی‌گرداند.

do_clear(arg)

مدیریت کنید که یک نقطه‌توقف در صورت موقتی بودن چگونه باید حذف شود.

این متد باید توسط کلاس‌های مشتق‌شده پیاده‌سازی شود.

کلاس‌های مشتق‌شده و کلاینت‌ها می‌توانند متدهای زیر را برای تأثیرگذاری بر وضعیت گام‌برداری فراخوانی کنند.

set_step()

پس از یک خط کد متوقف شوید.

set_next(frame)

در خط بعدی در فریم داده‌شده یا پایین‌تر از آن متوقف می‌شود.

set_return(frame)

در هنگام بازگشت از فریم داده‌شده، متوقف شود.

set_until(frame, lineno=None)

هنگام رسیدن به سطری با lineno بزرگ‌تر از خط جاری یا هنگام بازگشت از فریم جاری، متوقف شوید.

set_trace([frame])

اشکال‌زدایی را از frame شروع کنید. اگر frame مشخص نشده باشد، اشکال‌زدایی از فریم فراخواننده شروع می‌شود.

تغییر یافته در نسخه‌ی 3.13: set_trace() بلافاصله وارد اشکال‌زدا می‌شود، نه در خط بعدی کدی که قرار است اجرا شود.

set_continue()

فقط در نقطه‌های شکست یا هنگام پایان متوقف شوید. اگر هیچ نقطه‌ی شکستی وجود ندارد، تابع ردگیری سیستم را روی None تنظیم کنید.

set_quit()

ویژگی quitting را روی True تنظیم کنید. این کار باعث پرتاب BdbQuit در فراخوانی بعدی یکی از متدهای dispatch_*() می‌شود.

کلاس‌های مشتق‌شده و کلاینت‌ها می‌توانند متدهای زیر را برای دستکاری نقاط شکست فراخوانی کنند. این متدها در صورت بروز مشکل، رشته‌ای حاوی پیام خطا برمی‌گردانند، یا اگر همه‌چیز درست باشد None برمی‌گردانند.

set_break(filename, lineno, temporary=False, cond=None, funcname=None)

یک نقطه توقف جدید تنظیم می‌کند. اگر خط lineno برای filename که به‌عنوان آرگومان ارسال شده است وجود نداشته باشد، پیام خطایی برمی‌گرداند. filename باید به شکل کانونیکال (canonical form) باشد، همان‌طور که در متد canonic() توضیح داده شده است.

clear_break(filename, lineno)

نقاط شکست را در filename و lineno حذف کنید. اگر هیچ نقطه شکستی تنظیم نشده باشد، یک پیام خطا برگردانید.

clear_bpbynumber(arg)

نقطه توقفی را که در Breakpoint.bpbynumber اندیس arg دارد، حذف کنید. اگر arg عددی نباشد یا خارج از محدوده باشد، پیام خطایی برگردانده می‌شود.

clear_all_file_breaks(filename)

تمام نقاط شکست در filename را حذف کنید. اگر هیچ نقطه شکستی تنظیم نشده باشد، پیام خطایی برمی‌گرداند.

clear_all_breaks()

تمام نقاط شکست موجود را حذف می‌کند. اگر هیچ نقطه شکستی تنظیم نشده باشد، پیام خطایی برمی‌گرداند.

get_bpbynumber(arg)

نقطه توقف مشخص‌شده با شماره‌ی داده‌شده را برمی‌گرداند. اگر arg یک رشته باشد، به یک عدد تبدیل خواهد شد. اگر arg یک رشته غیرعددی باشد، اگر نقطه توقف داده‌شده هرگز وجود نداشته یا حذف شده باشد، استثنای ValueError پرتاب می‌شود.

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

get_break(filename, lineno)

اگر برای lineno در filename نقطه توقفی وجود داشته باشد، True برمی‌گرداند.

get_breaks(filename, lineno)

تمام نقاط توقف برای lineno در filename را برمی‌گرداند، یا اگر هیچ‌کدام تنظیم‌نشده باشند، یک فهرست خالی برمی‌گرداند.

get_file_breaks(filename)

تمام نقطه‌شکست‌های filename را برمی‌گرداند، یا در صورتی که هیچ نقطه‌شکستی تنظیم نشده باشد، یک فهرست خالی برمی‌گرداند.

get_all_breaks()

تمام نقطه‌توقف‌های تنظیم‌شده را برمی‌گرداند.

کلاس‌های مشتق‌شده و کلاینت‌ها می‌توانند متدهای زیر را برای غیرفعال کردن و راه‌اندازی مجدد رویدادها فراخوانی کنند تا به عملکرد بهتری دست یابند. این متدها تنها زمانی کار می‌کنند که از بک‌اند 'monitoring' استفاده شود.

disable_current_event()

رویداد فعلی را تا دفعه بعدی که restart_events() فراخوانی شود، غیرفعال می‌کند. این کار زمانی مفید است که خط فعلی برای اشکال‌زدا مهم نباشد.

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

restart_events()

همه رویدادهای غیرفعال را دوباره راه‌اندازی می‌کند. این تابع به‌طور خودکار در متدهای dispatch_* پس از فراخوانی متدهای user_* فراخوانی می‌شود. اگر متدهای dispatch_* بازنویسی‌نشده باشند، رویدادهای غیرفعال پس از هر تعامل کاربر دوباره راه‌اندازی می‌شوند.

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

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

get_stack(f, t)

فهرستی از تاپل‌های (frame, lineno) در یک ردگیری پشته، و یک اندازه را برمی‌گرداند.

آخرین فریم فراخوانی‌شده، در انتهای فهرست قرار دارد. اندازه، تعداد فریم‌های زیر فریمی است که اشکال‌زدا در آن فراخوانی شده است.

format_stack_entry(frame_lineno, lprefix=': ')

یک رشته حاوی اطلاعات درباره یک ورودی پشته برمی‌گرداند، که یک تاپل (frame, lineno) است. رشته بازگشتی شامل:

  • نام پرونده کانونیکالی که فریم در آن قرار دارد.

  • نام تابع یا "<lambda>".

  • آرگومان‌های ورودی.

  • مقدار بازگشتی.

  • خط کد (در صورت وجود).

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

run(cmd, globals=None, locals=None)

اشکال‌زدایی دستوری که از طریق تابع exec() اجرا می‌شود. globals به‌طور پیش‌فرض __main__.__dict__ است، locals به‌طور پیش‌فرض globals است.

runeval(expr, globals=None, locals=None)

اشکال‌زدایی یک عبارت اجراشده از طریق تابع eval(). globals و locals همان معنای خود در run() را دارند.

runctx(cmd, globals, locals)

برای سازگاری با نسخه‌های قدیمی. متد run() را فراخوانی می‌کند.

runcall(func, /, *args, **kwds)

یک فراخوانی تابع واحد را اشکال‌زدایی کنید و نتیجه‌ی آن را برگردانید.

در نهایت، این ماژول توابع زیر را تعریف می‌کند:

bdb.checkfuncname(b, frame)

بسته به روشی که Breakpoint b تنظیم شده است، اگر باید در اینجا توقف کنیم، True را برمی‌گرداند.

اگر از طریق شماره خط تنظیم شده باشد، بررسی می‌کند که آیا b.line با شماره خط موجود در frame یکسان است یا خیر. اگر نقطه توقف از طریق نام تابع تنظیم شده باشد، باید بررسی کنیم که در frame صحیح (تابع صحیح) و روی اولین خط قابل‌اجرای آن قرار داریم.

bdb.effective(file, line, frame)

(active breakpoint, delete temporary flag) یا (None, None) را به‌عنوان نقطه توقفی که باید بر اساس آن اقدام شود برمی‌گرداند.

نقطه توقف فعال اولین ورودی در bplist برای (file، line) (که باید وجود داشته باشد) است که enabled باشد، checkfuncname() برای آن درست باشد، و نه condition نادرست باشد و نه شمار ignore مثبت باشد. پرچم، به این معنا که یک نقطه توقف موقت باید حذف شود، تنها زمانی False است که نتوان cond را ارزیابی کرد (در این حالت، شمار ignore نادیده گرفته می‌شود).

اگر چنین ورودی‌ای وجود نداشته باشد، (None, None) برگردانده می‌شود.

bdb.set_trace()

شروع اشکال‌زدایی با نمونه‌ای از Bdb از فریم فراخواننده.