Tools/Debugging/Python Trace

From Blender Developer Wiki
Jump to: navigation, search

Tracing Python Code

Tracing code is a handy way to check what the code is doing, where stepping over line by line is impractical.

If a certain operation isn't behaving properly you can trace the execution of the working & failing state, then view their differences to see at which point the code-path diverges.

The 'trace' module

This example shows how to use the trace Python module to trace script execution.;711e3564b808ab802c503409e7740b0ca9b6ef65$68

The function call shows:

# Initializes Python classes.
# (good place to run a profiler or trace).

This example shows how a the function call can be traced.

import trace
tracer = trace.Trace(
        ignoredirs=[sys.prefix, sys.exec_prefix],
tracer.runctx('utils.load_scripts()', globals=globals(), locals=locals())

This traces all script execution on startup (addon registration, module imports... etc).

Heres an example of what the output may look like.

 --- modulename: __init__, funcname: <module>
<string>(1):  --- modulename: __init__, funcname: load_scripts     use_time =     if use_time:     loaded_modules = set()     if refresh_scripts:     if reload_scripts:     def register_module_call(mod):     def unregister_module_call(mod):     def test_reload(mod):     def test_register(mod):     if reload_scripts:     from bpy_restrict_state import RestrictBlend
 --- modulename: bpy_restrict_state, funcname: <module> """     "RestrictBlend", import bpy as _bpy class _RestrictContext:
 --- modulename: bpy_restrict_state, funcname: _RestrictContext class _RestrictContext:     __slots__ = ()     _real_data =     _real_pref = _bpy.context.user_preferences     @property     @property class _RestrictData:
 --- modulename: bpy_restrict_state, funcname: _RestrictData class _RestrictData:     __slots__ = () _context_restrict = _RestrictContext() _data_restrict = _RestrictData() class RestrictBlend:
 --- modulename: bpy_restrict_state, funcname: RestrictBlend class RestrictBlend:     __slots__ = ("context", "data")     def __enter__(self):     def __exit__(self, type, value, traceback):     with RestrictBlend():
 --- modulename: bpy_restrict_state, funcname: __enter__ =         self.context = _bpy.context = _data_restrict         _bpy.context = _context_restrict         for base_path in script_paths():
 --- modulename: __init__, funcname: script_paths     scripts = list(_scripts)     if check_all:         base_paths = _bpy_script_paths()     for path in base_paths + (script_path_user(), script_path_pref()):
 --- modulename: __init__, funcname: script_path_user     path = _user_resource('SCRIPTS')     return _os.path.normpath(path) if path else None
 --- modulename: __init__, funcname: script_path_pref     path = _user_preferences.filepaths.script_directory     return _os.path.normpath(path) if path else None         if path:             path = _os.path.normpath(path)             if path not in scripts and _os.path.isdir(path):                 scripts.append(path)

-- snip (around 40k lines) --