A "simple" library to help analyze issues post-mortem without a debugger attached.
You can use yasdu.dump() to dump the process state.
Be careful:
- Dumps like this can contain sensitive data, like passwords, authentication tokens etc. SHARE THEM WITH EXTREME CAUTION.
yasdu.dumpwill not overwrite files and will createfilename.numberfiles.
import yasdu
yasdu.dump('dump.json', 'Comment here')
# *** Created stack dump in 'dump.json' ***
# => 'dump.json'
# 'dump.json' is actual filename the dump was saved in
yasdu.dump('dump.json', 'Comment here')
# *** Created stack dump in 'dump.json.1' ***
# => 'dump.json.1'
# Since 'dump.json' already exists, the library picked 'dump.json.1'The yasdu.hook() function will hook sys.excepthook and if there's an uncaught
exception killing the program it will dump the process state into yasdu_autodump_[ISODATETIME].json
See hook and crash example
For the CLI IPython is recommended but not needed.
usage: yasdu [-h] -l FILE [-S] [-y]
optional arguments:
-l FILE, --load FILE Loads given file and starts a Python interpreter
-S, --no-sources Disables reading the sources from disk and showing them, useful if they have changed.
-y Assume yes to all questions
-h, --help show this help message and exit
Example:
$ python examples/hook_and_crash.py
*** Created stack dump in 'yasdu_autodump.json' ***
Traceback (most recent call last):
File "examples/hook_and_crash.py", line 13, in <module>
happily_convert_some_values()
File "examples/hook_and_crash.py", line 8, in happily_convert_some_values
v2 = int('deadbeef') # oh noes
ValueError: invalid literal for int() with base 10: 'deadbeef'Let's inspect the automatic dump.
$ yasdu -l yasdu_autodump.json
Loading dump files can allow them to execute code. Do you still want to proceed? [y/N]y
Unpickled 9 objects...
Done loading data.
# exception traceback generated by the program ↓
This is an automatic dump it has been triggered by an exception:
Traceback (most recent call last):
File "examples/hook_and_crash.py", line 13, in <module>
happily_convert_some_values()
File "examples/hook_and_crash.py", line 8, in happily_convert_some_values
v2 = int('deadbeef') # oh noes
ValueError: invalid literal for int() with base 10: 'deadbeef'
# stack data saved in the dump and sources loaded from disk
Available frames
0. examples/hook_and_crash.py:13 happily_convert_some_values() <-- # we're here
1. examples/hook_and_crash.py:8 v2 = int('deadbeef') # oh noes
LoadedFrame object is available through the `_lframe` global variable
Using IPython for shell...
# [snip]
[hook_and_crash.py:13 (0)] In [1]: sources()
import yasdu
some_global_variable = 'testing123'
def happily_convert_some_values():
v1 = int('deadbeef', 16)
v2 = int('deadbeef') # oh noes
if __name__ == '__main__':
yasdu.hook()
-> happily_convert_some_values()
[hook_and_crash.py:13 (0)] In [2]: down()
Available frames
0. examples/hook_and_crash.py:13 happily_convert_some_values()
1. examples/hook_and_crash.py:8 v2 = int('deadbeef') # oh noes <--
[hook_and_crash.py:13 (0)] In [3]: sources()
import yasdu
some_global_variable = 'testing123'
def happily_convert_some_values():
v1 = int('deadbeef', 16)
-> v2 = int('deadbeef') # oh noes
if __name__ == '__main__':
yasdu.hook()
happily_convert_some_values()
# variables are loaded from the dump
[hook_and_crash.py:13 (0)] In [4]: v1
Out[4]: 3735928559
[hook_and_crash.py:13 (0)] In [5]: some_global_variable
Out[5]: 'testing123'