Package: ddebug
ddebugddebug is a python library with a set of tools for simple debugging of python progams. It works only within a python file, not in the console.ddebug is bothicecream,snoopandrich.ddebug works with python 3.6+.InstallationInstall using pip:(python -m) pip install ddebug[full].if you want only the main dependencies (without dd.watch,dd.diff,pdbr and inputtimeout) you can install withpip install ddebug.if you want all but the special pdb post (pdbr and input with timeout) in excepthook you can install withpip install ddebug[no-pdbr].Simple Examplefromddebugimportdd@dd# do @snoop on a functiondeffoo(n):returnn+333@dd# do @snoop on all class functions (only possible in ddebug)classA:defbar(self,n):returnn+333dd(A().bar(foo(123)))# use like icecream.output:12:00:00.00>>>CalltofooinFile"python file.py",line312:00:00.00......n=12312:00:00.003|deffoo(n):12:00:00.004|returnn+33312:00:00.00<<<Returnvaluefromfoo:45612:00:00.00>>>CalltoA.barinFile"python file.py",line712:00:00.00..........self=<__main__.Aobjectat0x04F64E80>12:00:00.00..........n=45612:00:00.007|defbar(self,n):12:00:00.008|returnn+33312:00:00.00<<<ReturnvaluefromA.bar:789dd|A().bar(foo(123)):789TracebacksInddebugthere is an option for more detailed (and more beautiful) traceback than the regular traceback:fromddebugimportdd#place at start of programdd.set_excepthook()Then when an error occurrsddebugcreates a file named<file>-errors.txt:
the file starts withrich(render Python tracebacks with syntax highlighting and formatting)
and thenfriendlyexplanation of the error.and ddebug will print all this file in colors.In addition, you can press Enter within the first 5 seconds after exception and it will open thepdbr debugger.
if pdbr has a error, ddebug will start standard pdb.If you don't want\can't use excepthook (because usually other modules use the excepthook), you can useatexit:fromddebugimportdddd.set_atexit()if you want to choose file name:
passfile=<file>to the function.if you want ddebug only print to console (without file):
passwith_file=Falseto the function.you can control ddebug usage of pdbr debugger automatically with system variableddebug_pdb:
setddebug_pdb=1to set the input always to True
setddebug_pdb=0to set the input always to False
setddebug_pdb=Noneor deleteddebug_pdbto not set the inputnote: ddebug will ask for input only in real console (e.g. for windows: cmd.exe). and not in piped terminal (for windows:pycharm run python files)Usage without Importmodify/Create{python_path}\sitecustomize.pyfor windows is usually:%LocalAppData%\Programs\Python\Python38-32or if you have python 3.9%LocalAppData%\Programs\Python\Python39for linux and macos is usually:/usr/lib/python3.X/where X is your python minor versiontry:fromddebugimportddexceptImportError:passelse:__builtins__['dd']=ddand then you can just useddwithout dofrom ddebug import ddMore optionsprint stackddebug has a beautiful debug tool for print stack (to see the current stack without raising an error):just do:fromddebugimportdd#  print stack like tracebackdd.print_stack()# print stack like traceback only last 3 callsdd.print_stack(block=3)print_exceptionyou can also useddebug traceback(without pdbr and the files) in try/except:fromddebugimportddtry:1/0exceptException:dd.print_exception()ddebug also has shortcut for this usinglog_error(named also except_error):withdd.log_error():1/0or in function:@dd.log_error_function# named also except_error_functiondeftest():return1/0test()excddebug also has shortcut that connects all of theprint_exceptionshortcut namedexc.you can use it as normalprint_exception(bydd.exc()),log_error(by@dd.exc) andlog_error_function(bywith dd.exc)watchddebughas awatchandunwatch(named alsowandunw) usingwatchpoints.fromddebugimportdda=[]dd.watch(a)a={}OutputWatchtrigger:::File"python-file.py",line4,in<module>
a:was[]isnow{}By default all of this output is printed tosys.stderr.
If you want to change this, do:fromddebugimportddimportsysdd.watch_stream=sys.stdout# or another file/stream as you wantsnoop common argumentsYou canconfig snoop common argumentswithdd.snoop_short_config(named also ssc) with:fromddebugimportdddd.snoop_short_config(watch=('foo.bar','self.x["whatever"]'),watch_explode=['foo','self'])@dd.ssc(watch=('foo.bar','self.x["whatever"]'))# you even use that as the @dddeffoo(n):returnn+333foo(123)diffddebug can show difference bitween two objects usingdeepdiff(ddebug also formats this using rich):min cls:Sometimes you don't want to view all the class functions internal processes, just see when it was called. Then you can use mincls(named also mc) option to just see the function call:fromddebugimportdd@dd.minclsclassA:defa(self):passa=A()a.a()Output:dd|python-file.py:8in<module>:callmethod'a'fromclass'A'at11:34:15.383mincls does not yet support the __ <> __  functions(e.g. __ init __).timeitddebug can run function in loop and return|print the average time by thetimeitcommand (named alsodd.time):fromddebugimportdd@dd.timeit()deff(a,b):a+bf(2,2)Output:0.100000000-timeitonfunctionf-(running1000000times)localsddebug can print all locals in colors by the command:fromddebugimportdda="ddebug"b="-"c="locals"dd.locals()ConcatenatingIf you use ddebug as a function like icecream, e.g.dd(value)it will return the arguments you passed in to it:fromddebugimportdda="a"b="b"c=dd(dd(a)+dd(b))dd(c)Output:dd|a:'a'dd|b:'b'dd|dd(a)+dd(b):'ab'dd|c:'ab'Operationsdd has a lot of operations that are equal todd(a):fromddebugimportdda="a"b=dd+ab=dd*ab=dd@ab=dd>>ab=dd<<ab=a|ddb=dd|ab=dd&afor example: instead of trying to adddd()tol = list(map(str,filter(bool,range(12))))you can dol = dd @ list(map(str,filter(bool,range(12))))Don't use<>=(e.g.+=) operations. icecream can't get source code and will throw a ScoreError.install()To make dd available in every file (without needing to import ddebug) just write in the first file:fromddebugimportdddd.install()# install only "dd" name# you can chose an aliasdd.install(("dd","d"))Disablingdd has an attribute namedenabled. Set to false to suppress output.fromddebugimportdddd(12)# will output ic(12)dd.enabled=Falsedd(12)# not output anythingThis disabes all ddebug tools except for the dd-tracebacks.StreamsIf you want to write ddebug output to tmp file (likeq) and also to stderr just do:dd.add_tmp_stream()If you want only a tmp file(without stderr):dd.add_tmp_stream(with_print=False)if you want to write only to custom file do:dd.stream=open("output.txt","w")Don't forget to close the file.If you do not close the file - the file will probably not write.
My recommendation is to use built-inatexitmodule to close the file (you can use it even if you alredy use atexit (e.g.dd.set_atexit()):importatexitfromddebugimportddoutput_stream=open("output.txt","w")atexit.register(output_stream.close)#will close the file at the end of the programdd.stream=output_streamAll of them will remove color from stderr print.All of them will affect all ddebug tools except the Tracebacks.Output folderIf you want to see all the output of ddebug in one folder you can do:fromddebugimportdddd.add_output_folder()# then all output goes to folder and stderr - it will also remove color.it will create a folder named<file>_logand create 4 .txt files:watch-log- output fromdd.<un>watchsnoop-log- output from@ddon class or function and fromdd.deepicecream-log- output fromdd()and@dd.mincls.rich-log- output fromdd.pprint,dd.inspect,dd.diffanddd.print_stack()It will also set excepthook or atexit to create a file namederror.txtin this folder.
Passwith_errors=Falseto this function to prevent this.If you dont want each run of the program to overwrite the files in the folder or you want to see the date your script was run - do:dd.add_output_folder(with_date=True)or:dd.add_output_folder(True)There is way to choose folder name using a file:dd.add_output_folder(pyfile="python-file.py")# will create a folder python-file_logor:dd.add_output_folder(folder="my-cool-folder")# will create a folder my-cool-folderconfigYou canconfig snoopwith:dd.snoopconfig(snoop-config-options).
All options but builtins and snoop names are valid.configicecream.includeContext(dd() calls filename, line number, and parent function to dd output.) by:dd.icecream_includeContext = True.configfriendly.languagebydd.friendly_lang = "<languages>"configrich color-systemby:dd.rich_color_system = <color-system>with ddwith ddequal towith snoop.more debbug tools:inspect()dd.inspect(obj)equal torich.inspectpprint()dd.pprintwiil pretty print the variable using richdeep()dd.deepequal tosnoop.pp.deepDependenciesddebug depends on the python librarys:snoop- main dependencyrich-  main dependencyicecream- main dependencyfriendly- for explanation on the error in Tracebeckspdbr- for make the pdb more colorful.inputimeout- for ask to start pdbr debugger in Tracebeckswatchpoints- fordd.watchanddd.unwatchdeepdiff- fordd.diffContributeOn all errors, problems or suggestions please open agithub issueIf you found this library useful, it would be great if you could buy me a coffee: