Debugger#
Note
This page serves as a starting point to design and implement a debugger for WebTJ 3.
Ressources#
https://mostlynerdless.de/blog/2023/09/20/lets-create-a-python-debugger-together-part-1/
https://florian-dahlitz.de/articles/how-to-debug-your-python-code
Writing a step by step expression evaluation debugger like Thonny : https://stackoverflow.com/questions/40639652/tracing-python-expression-evaluation-step-by-stepb
Using the bdb
module#
import bdb
import inspect
import os
class Mydb(bdb.Bdb):
def head(self, frame):
return f'{os.path.basename(frame.f_code.co_filename)}: {frame.f_lineno} :'
def hprint(self, frame, *args, **kwargs):
print(self.head(frame), *args, **kwargs)
def user_call(self, frame, arg):
# arg is None (see the doc of sys.settrace)
L, n = inspect.getsourcelines(frame)
print(L, n)
self.hprint(frame, f'-> {L[frame.f_lineno - n].rstrip()} {frame.f_locals}')
input("next")
def user_line(self, frame):
L, n = inspect.getsourcelines(frame)
self.hprint(frame, L[frame.f_lineno - n], end='')
input("next")
def user_return(self, frame, value):
L, n = inspect.getsourcelines(frame)
self.hprint(frame, f'<- {frame.f_code.co_name}: {value}')
def eggs(x):
return x + x
def spam(a, b):
return f'{eggs(b)} {eggs(a)}'
def main():
x = 2 + 2
spam(7, 'ham')
return x
if __name__ == '__main__':
mydb = Mydb()
mydb.runcall(main)
It also works with sleep#
import bdb
import inspect
import os
from time import sleep
wait_time = 1
class Mydb(bdb.Bdb):
def head(self, frame):
return f'{os.path.basename(frame.f_code.co_filename)}: {frame.f_lineno} :'
def hprint(self, frame, *args, **kwargs):
print(self.head(frame), *args, **kwargs)
def user_call(self, frame, arg):
# arg is None (see the doc of sys.settrace)
L, n = inspect.getsourcelines(frame)
print(L, n)
self.hprint(frame, f'-> {L[frame.f_lineno - n].rstrip()} {frame.f_locals}')
sleep(wait_time)
def user_line(self, frame):
L, n = inspect.getsourcelines(frame)
self.hprint(frame, L[frame.f_lineno - n], end='')
sleep(wait_time)
def user_return(self, frame, value):
L, n = inspect.getsourcelines(frame)
self.hprint(frame, f'<- {frame.f_code.co_name}: {value}')
sleep(wait_time)
def eggs(x):
return x + x
def spam(a, b):
return f'{eggs(b)} {eggs(a)}'
def main():
x = 2 + 2
spam(7, 'ham')
return x
if __name__ == '__main__':
mydb = Mydb()
mydb.runcall(main)