{"id":28965428,"url":"https://github.com/matan-h/ddebug","last_synced_at":"2025-06-24T06:11:21.684Z","repository":{"id":39615227,"uuid":"331309472","full_name":"matan-h/ddebug","owner":"matan-h","description":"python library with a set of tools for simple debugging of python programs","archived":false,"fork":false,"pushed_at":"2023-04-17T23:58:24.000Z","size":189,"stargazers_count":19,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-10T10:03:42.723Z","etag":null,"topics":["ddebug","debug","icecream","python","rich","snoop","tools"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matan-h.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-20T13:05:44.000Z","updated_at":"2024-10-07T12:32:59.000Z","dependencies_parsed_at":"2022-09-03T08:51:32.064Z","dependency_job_id":null,"html_url":"https://github.com/matan-h/ddebug","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/matan-h/ddebug","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matan-h%2Fddebug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matan-h%2Fddebug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matan-h%2Fddebug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matan-h%2Fddebug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matan-h","download_url":"https://codeload.github.com/matan-h/ddebug/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matan-h%2Fddebug/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261057701,"owners_count":23103706,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ddebug","debug","icecream","python","rich","snoop","tools"],"created_at":"2025-06-24T06:11:21.058Z","updated_at":"2025-06-24T06:11:21.658Z","avatar_url":"https://github.com/matan-h.png","language":"Python","funding_links":["https://www.buymeacoffee.com/matanh"],"categories":[],"sub_categories":[],"readme":"# ddebug\nddebug 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.\n\nddebug is both\n[icecream](https://github.com/gruns/icecream),\n[snoop](https://github.com/alexmojaki/snoop) and [rich](https://github.com/willmcgugan/rich).\n\nddebug works with python 3.6+.\n\n## Installation\nInstall using pip: ```(python -m) pip install ddebug[full]```.\n\nif you want only the main dependencies (without dd.watch,dd.diff,pdbr and inputtimeout) you can install with `pip install ddebug`.\n\nif you want all but the special pdb post (pdbr and input with timeout) in excepthook you can install with `pip install ddebug[no-pdbr]`.\n\n\n## Simple Example\n```python\nfrom ddebug import dd\n@dd  # do @snoop on a function\ndef foo(n):\n    return n + 333\n@dd  # do @snoop on all class functions (only possible in ddebug)\nclass A:\n    def bar(self, n):\n        return n + 333\n\ndd(A().bar(foo(123)))  # use like icecream.\n```\noutput:\n```shell\n12:00:00.00 \u003e\u003e\u003e Call to foo in File \"python file.py\", line 3\n12:00:00.00 ...... n = 123\n12:00:00.00    3 | def foo(n):\n12:00:00.00    4 |     return n + 333\n12:00:00.00 \u003c\u003c\u003c Return value from foo: 456\n12:00:00.00 \u003e\u003e\u003e Call to A.bar in File \"python file.py\", line 7\n12:00:00.00 .......... self = \u003c__main__.A object at 0x04F64E80\u003e\n12:00:00.00 .......... n = 456\n12:00:00.00    7 |     def bar(self, n):\n12:00:00.00    8 |         return n + 333\n12:00:00.00 \u003c\u003c\u003c Return value from A.bar: 789\ndd| A().bar(foo(123)): 789\n```\n## Tracebacks\nIn `ddebug` there is an option for more detailed (and more beautiful) traceback than the regular traceback:\n\n```python\nfrom ddebug import dd\n#place at start of program\ndd.set_excepthook()\n```\nThen when an error occurrs `ddebug` creates a file named `\u003cfile\u003e-errors.txt`:\nthe file starts with [rich](https://github.com/willmcgugan/rich) (render Python tracebacks with syntax highlighting and formatting)\nand then  [friendly](https://github.com/aroberge/friendly) explanation of the error.\n\nand ddebug will print all this file in colors.\n\nIn addition, you can press Enter within the first 5 seconds after exception and it will open the\n[pdbr debugger](https://github.com/cansarigol/pdbr).\nif pdbr has a error, ddebug will start standard pdb.\n\n![ddebug traceback image](https://github.com/matan-h/ddebug/blob/master/images/traceback.png?raw=true)\n\nIf you don't want\\\\can't use excepthook (because usually other modules use the excepthook), you can use `atexit`:\n```python\nfrom ddebug import dd\ndd.set_atexit()\n```\nif you want to choose file name:\npass `file=\u003cfile\u003e` to the function.\n\nif you want ddebug only print to console (without file):\npass `with_file=False` to the function.\n\nyou can control ddebug usage of pdbr debugger automatically with system variable `ddebug_pdb`:\nset `ddebug_pdb=1` to set the input always to True\nset `ddebug_pdb=0` to set the input always to False\nset `ddebug_pdb=None` or delete `ddebug_pdb` to not set the input\n\nnote: 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)\n## Usage without Import\nmodify/Create `{python_path}\\sitecustomize.py`\n\nfor windows is usually: `%LocalAppData%\\Programs\\Python\\Python38-32` or if you have python 3.9 `%LocalAppData%\\Programs\\Python\\Python39`\n\nfor linux and macos is usually:`/usr/lib/python3.X/`  where X is your python minor version\n\n```python\ntry:\n    from ddebug import dd\nexcept ImportError:\n    pass\nelse:\n    __builtins__['dd'] = dd\n```\nand then you can just use `dd` without do `from ddebug import dd`\n\n\n## More options\n### print stack\nddebug has a beautiful debug tool for print stack (to see the current stack without raising an error):\n\n![ddebug print_stack image](https://github.com/matan-h/ddebug/blob/master/images/print_stack.png?raw=true)\n\njust do:\n```python\nfrom ddebug import dd\n#  print stack like traceback\ndd.print_stack()\n# print stack like traceback only last 3 calls\ndd.print_stack(block=3)\n```\n### print_exception\nyou can also use [ddebug traceback](#Tracebacks) (without pdbr and the files) in try/except:\n```python\nfrom ddebug import dd\ntry:\n    1/0\nexcept Exception:\n    dd.print_exception()\n```\nddebug also has shortcut for this using `log_error` (named also except_error):\n```python\nwith dd.log_error():\n    1/0\n```\nor in function:\n```python\n@dd.log_error_function # named also except_error_function\ndef test():\n    return 1/0\ntest()\n```\n#### exc\nddebug also has shortcut that connects all of the `print_exception` shortcut named `exc`.\n\nyou can use it as normal `print_exception` (by `dd.exc()`),`log_error` (by `@dd.exc`) and `log_error_function` (by `with dd.exc`)\n### watch\n`ddebug` has a `watch` and `unwatch` (named also `w` and `unw`) using [watchpoints](https://github.com/gaogaotiantian/watchpoints).\n```python\nfrom ddebug import dd\na = []\ndd.watch(a)\na = {}\n```\nOutput\n\n```shell\nWatch trigger ::: File \"python-file.py\", line 4, in \u003cmodule\u003e\na:was [] is now {}\n```\n\nBy default all of this output is printed to `sys.stderr`.\nIf you want to change this, do:\n\n```python\nfrom ddebug import dd\nimport sys\ndd.watch_stream = sys.stdout # or another file/stream as you want\n```\n### snoop common arguments\nYou can [config snoop common arguments](https://github.com/alexmojaki/snoop#common-arguments) with  `dd.snoop_short_config` (named also ssc) with:\n```python\nfrom ddebug import dd\ndd.snoop_short_config(watch=('foo.bar', 'self.x[\"whatever\"]'),watch_explode=['foo', 'self'])\n@dd.ssc(watch=('foo.bar', 'self.x[\"whatever\"]'))   # you even use that as the @dd\ndef foo(n):\n  return n+333\nfoo(123)\n  ```\n### diff\nddebug can show difference bitween two objects using [deepdiff](https://github.com/seperman/deepdiff) (ddebug also formats this using rich):\n\n![ddebug difference image](https://github.com/matan-h/ddebug/blob/master/images/diff.png?raw=true)\n\n### min cls:\nSometimes 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:\n```python\nfrom ddebug import dd\n@dd.mincls\nclass A:\n    def a(self):\n        pass\n\na = A()\na.a()\n```\nOutput:\n```shell\ndd| python-file.py:8 in \u003cmodule\u003e: call method 'a' from class 'A' at 11:34:15.383\n```\nmincls does not yet support the __ \u003c\u003e __  functions(e.g. __ init __).\n### timeit\nddebug can run function in loop and return|print the average time by the `timeit` command (named also `dd.time`):\n```python\nfrom ddebug import dd\n@dd.timeit()\ndef f(a, b):\n    a + b\nf(2,2)\n```\nOutput:\n```shell\n0.100000000 - timeit on function f - (running 1000000 times)\n```\n### locals\nddebug can print all locals in colors by the command:\n```python\nfrom ddebug import dd\na = \"ddebug\"\nb = \"-\"\nc = \"locals\"\ndd.locals()\n```\n### Concatenating\nIf you use ddebug as a function like icecream, e.g. `dd(value)` it will return the arguments you passed in to it:\n```python\nfrom ddebug import dd\na = \"a\"\nb = \"b\"\nc = dd(dd(a)+dd(b))\ndd(c)\n```\nOutput:\n```shell\ndd| a: 'a'\ndd| b: 'b'\ndd| dd(a)+dd(b): 'ab'\ndd| c: 'ab'\n```\n### Operations\ndd has a lot of operations that are equal to `dd(a)`:\n```python\nfrom ddebug import dd\na = \"a\"\nb = dd+a\nb = dd*a\nb = dd@a\nb = dd\u003e\u003ea\nb = dd\u003c\u003ca\nb = a|dd\nb = dd|a\nb = dd\u0026a\n```\nfor example: instead of trying to add `dd()` to `l = list(map(str,filter(bool,range(12))))`\nyou can do `l = dd @ list(map(str,filter(bool,range(12))))`\n\nDon't use `\u003c\u003e=`(e.g. `+=`) operations. icecream can't get source code and will throw a ScoreError.\n\n### install()\nTo make dd available in every file (without needing to import ddebug) just write in the first file:\n```python\nfrom ddebug import dd\ndd.install() # install only \"dd\" name\n# you can chose an alias\ndd.install((\"dd\",\"d\"))\n```\n\n### Disabling\ndd has an attribute named `enabled`. Set to false to suppress output.\n```python\nfrom ddebug import dd\ndd(12) # will output ic(12)\ndd.enabled = False\ndd(12) # not output anything\n```\nThis disabes all ddebug tools except for the dd-tracebacks.\n\n### Streams\nIf you want to write ddebug output to tmp file (like [q](https://github.com/zestyping/q)) and also to stderr just do:\n```python\ndd.add_tmp_stream()\n```\nIf you want only a tmp file(without stderr):\n```python\ndd.add_tmp_stream(with_print=False)\n```\nif you want to write only to custom file do:\n```python\ndd.stream = open(\"output.txt\",\"w\")\n```\n**Don't forget to close the file.**\nIf you do not close the file - the file will probably not write.\nMy recommendation is to use built-in`atexit` module to close the file (you can use it even if you alredy use atexit (e.g. `dd.set_atexit()`):\n```python\nimport atexit\nfrom ddebug import dd\noutput_stream = open(\"output.txt\", \"w\")\natexit.register(output_stream.close) #will close the file at the end of the program\ndd.stream = output_stream\n```\nAll of them will remove color from stderr print.\n\nAll of them will affect all ddebug tools except the Tracebacks.\n\n### Output folder\nIf you want to see all the output of ddebug in one folder you can do:\n```python\nfrom ddebug import dd\ndd.add_output_folder()  # then all output goes to folder and stderr - it will also remove color.\n```\nit will create a folder named `\u003cfile\u003e_log` and create 4 .txt files:\n* `watch-log` - output from `dd.\u003cun\u003ewatch`\n* `snoop-log` - output from `@dd` on class or function and from `dd.deep`\n* `icecream-log` - output from `dd()` and `@dd.mincls`.\n* `rich-log` - output from `dd.pprint`,`dd.inspect`,`dd.diff` and `dd.print_stack()`\n\nIt will also set excepthook or atexit to create a file named `error.txt` in this folder.\nPass `with_errors=False` to this function to prevent this.\n\nIf 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:\n```python\ndd.add_output_folder(with_date=True)\n```\nor:\n```python\ndd.add_output_folder(True)\n```\nThere is way to choose folder name using a file:\n```python\ndd.add_output_folder(pyfile=\"python-file.py\") # will create a folder python-file_log\n```\nor:\n```python\ndd.add_output_folder(folder=\"my-cool-folder\") # will create a folder my-cool-folder\n```\n### config\nYou can [config snoop](https://github.com/alexmojaki/snoop#output-configuration) with:\n`dd.snoopconfig(snoop-config-options)`.\nAll options but builtins and snoop names are valid.\n\n config `icecream.includeContext` (dd() calls filename, line number, and parent function to dd output.) by:`dd.icecream_includeContext = True`.\n\n config [`friendly.language`](https://aroberge.github.io/friendly-traceback-docs/docs/html/usage_adv.html#language-used) by `dd.friendly_lang = \"\u003clanguages\u003e\"`\n\n config [`rich color-system`](https://rich.readthedocs.io/en/stable/console.html#color-systems) by: `dd.rich_color_system = \u003ccolor-system\u003e`\n\n## with dd\n`with dd` equal to [`with snoop`](https://github.com/alexmojaki/snoop#basic-snoop-usage).\n\n## more debbug tools:\n### inspect()\n`dd.inspect(obj)` equal to [`rich.inspect`](https://github.com/willmcgugan/rich#rich-inspect)\n\n### pprint()\n`dd.pprint` wiil pretty print the variable using rich\n\n### deep()\n`dd.deep` equal to [`snoop.pp.deep`](https://github.com/alexmojaki/snoop#ppdeep-for-tracing-subexpressions)\n\n\n## Dependencies\nddebug depends on the python librarys:\n* [snoop](https://github.com/alexmojaki/snoop) - main dependency\n* [rich](https://github.com/willmcgugan/rich) -  main dependency\n* [icecream](https://github.com/gruns/icecream) - main dependency\n* [friendly](https://github.com/aroberge/friendly) - for explanation on the error in Tracebecks\n* [pdbr](https://github.com/cansarigol/pdbr) - for make the pdb more colorful.\n* [inputimeout](https://pypi.org/project/inputimeout) - for ask to start pdbr debugger in Tracebecks\n* [watchpoints](https://github.com/gaogaotiantian/watchpoints) - for `dd.watch` and `dd.unwatch`\n* [deepdiff](https://github.com/seperman/deepdiff) - for `dd.diff`\n\n## Contribute\nOn all errors, problems or suggestions please open a [github issue](https://github.com/matan-h/ddebug/issues)  \n\nIf you found this library useful, it would be great if you could buy me a coffee:  \n\n\u003ca href=\"https://www.buymeacoffee.com/matanh\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/default-blue.png\" alt=\"Buy Me A Coffee\" height=\"47\" width=\"200\"\u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatan-h%2Fddebug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatan-h%2Fddebug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatan-h%2Fddebug/lists"}