Debug module

class Debug.Debug[source]

Bases: object

This class will dump debug information into a debug log file.

In order for this to work, first you must set the options of the logger with at least a DEBUG_FILE parameter. You can do this by either calling Debug.set_debug_file(), or by calling Debug.set_config() with a dictionary with at least a DEBUG_FILE item.

All functions are static, you should not instantiate this class.

Once this class is correctly set up, you can start logging information by using any of the methods in this class. For instance, if you want to log an exception during a try-except, you can do so by using Debug.debugException() or Debug.debugCritical() for critical exceptions.

If you just want to log information, you can use Debug.debugLog() at any given time.

You can also use Debug.inspect() to inspect any object and dump it’s information. This is very useful when you want to print information related to a variable. If you want to inspect global variables or local variables, use Debug.inspectGlobals() or Debug.inspectLocals() respectively. There is also Debug.inspectModules() if you need to dump all loaded modules.

Last but not least, Debug.hexdump() will dump the contents of a bytes array into the log. If you want to dump binary data into a different file so you can inspect it later by other means, use Debug.bindump().

Example

from Debug import Debug

Debug.set_config({
    "DEBUG_FILE": "./debug/debug.log",
    "ROLLER_LINES": 25000,
    "WRITE_TO_STDOUT": True
})

try:
    a = 5
    b = 0
    c = a/b
except Exception as exc:
    Debug.debugException(exc)

This prints the following debug information into debug/debug.log:

-- START OF EXCEPTION (E 0xe7ba3afc) --
12/07/2022, 13:42:10:356113 E 0xe7ba3afc [<class 'ZeroDivisionError'>]
Traceback (most recent call last):
File "E:\PY\maira\debugTest.py", line 12, in <module>
c = a/b
ZeroDivisionError: division by zero

From: E:\PY\maira\debugTest.py 14 <module>
Context: ['    Debug.debugException(exc)']
locals():
local: __doc__ (<class 'NoneType'>) -> None
local: __package__ (<class 'NoneType'>) -> None
local: __spec__ (<class 'NoneType'>) -> None
local: __cached__ (<class 'NoneType'>) -> None
local: Debug (<class 'type'>) ->
12/07/2022, 13:42:10:357113 L 0x983305b7 [instance of type]
   WARNING: Objects instances of type are ignored due to deep recursion.
END of local: Debug
local: a (<class 'int'>) -> 5
local: b (<class 'int'>) -> 0
local: exc (<class 'ZeroDivisionError'>) ->
12/07/2022, 13:42:10:358114 L 0x4616027d [instance of ZeroDivisionError]
   WARNING: This instance of ZeroDivisionError is empty
END of local: exc
-- END OF EXCEPTION --

Understanding logs

Each log has a header with the following information:

<datetime> <log ID> [<event name>]

datetime is the date and time of the log, up to milliseconds. log ID is a unique identifier for the log in the following format:

<log class> 0x<ID>

Where log class is the severity of the log (‘L’ for log/information, ‘E’ for Exception, and ‘C’ for Critical error), and ID is a unique identifier for the log.

event name is the name of the log event.

When debugging exceptions, the log is wrapped into the following headers:

-- START OF EXCEPTION (<log ID>) --

    ...

-- END OF EXCEPTION --

Everything between the start and the end of the exception, belongs to the exception being reported. The same applies for critical errors, except it says CRITICAL ERROR instead of EXCEPTION.

Exceptions and critical errors have a unique ID. Errors that generate in the same line of the code will all have the same ID. This will help you get track of errors as well.

When inspecting objects, the name, type and value of the object will be dumped. Class instances will also see their members dumped. The debugger will recursively dump all members of the object instance and add indentation depending on the level of recursion, until MAX_RECURSION is reached.

Warnings

You might see the following warnings in your log:

WARNING: <var num> variables not assigned: <list of not assigned>

Caused when inspecting locals or globals and passing a list with variable names, but some of the variables in the list are not assigned at this point.

WARNING: Recursion limit when calling <debug function>. Skipping.

Caused when MAX_RECURSION is reached while inspecting an object. At this point the debugger will not recurse into any of the object’s members any more.

WARNING: <name> (<object>) is empty

Caused when inspecting a list, dict or tuple that is empty.

WARNING: Attempting to call <function> on something that is not a <class>.

Caused when attempting to inspect a list, dict or tuple that is not an instance of their respective function’s intended class (i.e calling debugDict and passing a Tuple as a parameter). The debugger will tell you what it really is in the next line.

WARNING: Objects instances of <type> are ignored due to deep recursion.

Caused when attempting to inspect an object instance of a class that is known to cause deep recursion problems. Ignore these.

WARNING: Attempting to call 'debugClass' on object of type <type> (Not a class)

Caused when calling debugClass on something that doesn’t seem to be an instance of a class. For instance, calling debugClass and passing a dict as it’s parameter.

WARNING: This instance of <type> is empty

Caused when calling debugClass with an object instance that has no members (it’s empty). Functions are ignored.

Class functions

static bindump(obj: bytes, output_file: str, as_string: bool = False)[source]
Parameters
  • obj (bytes) – Object to dump

  • output_file (str) – File where the binary data will be output.

  • as_string (bool) – Output a string with the binary data instead of binary data, defaults to False

This function will dump binary data into output_file. If as_string is set to True, it will instead dump the binary data as hex by calling hexdump.

static debugClass(_instance: object, _rec: int = 0)[source]
Parameters

_instance (object) – Object instance of any class.

Inspects an instance object, dumping all the information from it.

static debugCritical(exc: Exception) int[source]
Parameters

exc (Exception) – The exception to debug

Call this function only for critical errors. It’s the same as debugException, but it logs at critical level ‘C’ and outputs the whole global and local frames as well as the loaded modules.

Returns

ID of the exception. The ID is a unique identifier for the exception, meaning that if the exception is the same, the same ID will be returned.

Return type

int

static debugDict(_dict: dict, name: str = '', _rec: int = 0)[source]
Parameters
  • _dict – Dictionary to inspect

  • name (str) – Name of the dictionary, optional, defaults to “”

This function will dump all key-value pairs from the given dictionary. ‘name’ is optional and it’s only used to give a name to the dict in the log.

static debugException(exc: Exception, inspect_globals: bool = False, inspect_global_vars: Optional[list] = None, inspect_locals: bool = True, inspect_local_vars: Optional[list] = None) int[source]
Parameters
  • exc (Exception) – The exception to debug

  • inspect_globals (bool) – Inspect globals or not, defaults to False

  • inspect_global_vars (list) – List of global variable names to inspect as strings, defaults to None

  • inspect_locals (bool) – Inspect locals or not, defaults to True

  • inspect_local_vars (list) – List of local variable names to inspect as strings, defaults to None

When either inspect_global_vars or inspect_local_vars is set to a list of names, it will attempt to inspect those variables. If set to None, it will inspect all variables in the global and local scopes respectively.

Returns

ID of the exception. The ID is a unique identifier for the exception, meaning that if the exception is the same, the same ID will be returned.

Return type

int

static debugListorTuple(_list: list, name: str = '', _rec: int = 0)[source]
Parameters
  • _list – List or tuple to inspcect

  • name (str) – Name of the list or tuple, optional, defaults to “”

This function will dump all items from the given list or tuple. ‘name’ is optional and it’s only used to give a name to the list or tuple in the log.

static debugLog(msg: str, name: str = '')[source]
Parameters
  • msg (str) – Message to log.

  • name (str) – Name of the event to log, defaults to “”

The parameter ‘name’ is just for decorative purposes only.

static getFrameInfo()[source]

Gets the caller current frame. It executes getframeinfo(currentframe().f_back)

static getGlobals()[source]

Gets the globals

static getLocals()[source]

Gets the locals from the caller perspective.

static getSystemInfo() dict[source]

Returns the system information as a dict containing the following information:

python: Python build version.
platform: Platform information.
cpu_name: Name of the processor architecture.
cpu_count: String containing the physical CPU count and the logical CPU count.
os: Name of the operating system.
memory dict with the following information:
virtual: Tuple with the virtual memory information.
swap: Swap memory information
used_by_python: Memory used by the program.
network: If the machine is connected to the internet, it’s set to True, False if it’s not.

All units are in bytes.

Note: To determine if it’s connected to the internet, this function makes a request to ipecho.net.

static hexdump(obj: bytes, start_offset: int = 0, end_offset: Optional[int] = None, cols: int = 16, rows: Optional[int] = None, split: int = 0, headers: bool = True, offsets: bool = True, ascii: bool = True, rawoutput: bool = False, forceasciionly=False) str[source]
Parameters
  • obj (bytes) – Byte array to dump.

  • start_offset (int) – Starting offset to dump, defaults to 0

  • end_offset (int) – End offset to dump, defaults to None

  • cols (int) – Columns to dump, defaults to 16

  • rows (int) – Rows to dump, defaults to None

  • split (int) – Split the dump into several tables at this many rows, defaults to 0

  • headers (bool) – Print the headers or not, defaults to True

  • offsets (bool) – Print the offsets or not, defaults to True

  • ascii (bool) – Will print the ASCII representation of the hex information, defaults to True

  • rawoutput (bool) – Will only print a table of hex bytes and nothing else, defaults to False

  • forceasciionly (bool) – Will only print printable characters (such as letters and numbers), defaults to False

Returns

String containing the hex dump, or None if the function fails

Return type

str or None

This function will return an hex dump in the style of an hex editor as a string. The parameters determine the format and the information dumped. When dumping information, by default the offset column will always start at 0. If you want to inspect a portion of the array, using start_offset and end_offset is recommended rather than slicing the array so that the output is accurate.

The output is in a table format in the style of hex editors. Each row represents a string of n bytes, and each column represents a byte. The parameters row and cols determine how many rows and how many columns can be represented. No more than 16 columns can be represented, and no less than 1 rows or columns can be represented.

The parameter split will split the output into smaller tables. It will split the table every n rows, where n is the value of split. So if split is set to 16, it will split the table every 16 rows.

The header is the top part of the table and the offsets are at the left of the table. They can be disables with the headers and offsets parameters if you don’t want them.

The ascii representation of the data will be printed at the right of the table, and can also be disabled with the ascii parameter.

If rawoutput is set to True, it will disable split, headers, offsets, and ascii. Set this to True if you want a raw output.

When storing hex dumps into files, enable forceasciionly to avoid non-ascii characters to be stored that could cause issues.

static inspect(obj: object)[source]
Parameters

obj (Any) – Object to inspect

Inspect an object.

static inspectGlobals(for_id: str = '', vars: Optional[list] = None)[source]
For_id

Ignore this parameter. It is used by the class.

Parameters

vars (list) – List of variable names to inspect as strings, defaults to None

If vars is set to None, it will inspect all globals.

static inspectLocals(l_: dict, vars: Optional[list] = None, for_id: str = '')[source]
Parameters
  • l (dict) – Dictionary with the locals.

  • vars (list) – List of variable names to inspect as strings, defaults to None

  • for_id (str) – Ignore this parameter (It is used by the class), defaults to “”

Use GetFrameInfo(currentframe()) to get the local variables. If vars is set to None, it will inspect all locals.

static inspectModules()[source]

This function will get all loaded modules and dump them into the log file.

static set_config(config: dict)[source]
Parameters

config (dict) – A dictionary with the Debugger configuration parameters.

Set the global configuration of the debugger. The configuration is in a dictionary object containing the paramenters and their respective values. The following values are accepted:

DEBUG_FILE (str): Path to the debug log where the information will be stored.
MAX_RECURSION (int): Sets the maximum allowed recursion while inspecting. (Default: 11)
WRITE_TO_STDOUT (bool): Output to the console. (Default: False)
VERBOSE_STDOUT (bool): Will output EVERYTHING to the console. (Default: False)
ROLLER (bool): Enable/disable the rolling log file (Default: True)
ROLLER_LINES (int): Maximum lines in the log until it starts rolling (Default: 50000)
DUMP_BYTES (bool): Will dump an hex representation of bytes objects (Default: True)
DUMP_BYTES_LENGTH (int): Maximum length (in bytes) of the dumps (Default: 512)

Notes: WRITE_TO_STDOUT will write to STDERR when calling to debugException or debugCritical.

static set_debug_file(path: str) TextIOWrapper[source]

Set the output file where the log will be stored.

static set_dump_bytes(dump_bytes: bool)[source]

Enable/Disable hex dumps of byte-like objects (bytes, ByteIO) during object inspection.

static set_dump_bytes_length(dump_bytes_length: int)[source]

When DUMP_BYTES is enabled, sets the maximum number of bytes to dump. :param dump_bytes_length: The maximum number of bytes to dump. Must be between 8 and 1000000.

static set_max_recursion(max_rec: int) bool[source]

Set the maximum recursion allowed when inspecting objects. :param max_rec: Maximum recursion. Must be between 1 and sys.getrecursionlimit() - 10. 10 recursions are reserved to avoid reaching maximum recursion. Set this to something relatively low (You shouldn’t need more than 10).

static set_roller_lines(roller_lines: int)[source]
Parameters

roller_lines – The number of lines. Must be between 1 and 10000000.

Set the maximum number of lines before the log starts rolling.

static set_roller_log(roller_log: bool = True)[source]

Enable/Disable rolling logs. When enabled, log files will delete the first lines if the number of lines is bigger than ROLLER_LINES.

static set_verbose_stdout(verbose_stdout: bool = True)[source]

When WRITE_TO_STDOUT is enabled, this will force the debugger to print EVERY line to the console.

static set_write_to_stdout(write_to_stdout: bool = True)[source]

Allow/disallow output to the console.