Dev:Doc/Tools/Debugging/Python Trace
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.
The function call shows:
# Initializes Python classes.
# (good place to run a profiler or trace).
utils.load_scripts()
This example shows how a the function call can be traced.
import trace
tracer = trace.Trace(
ignoredirs=[sys.prefix, sys.exec_prefix],
trace=1,
count=1,
)
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
__init__.py(145): use_time = _bpy.app.debug_python
__init__.py(147): if use_time:
__init__.py(151): loaded_modules = set()
__init__.py(153): if refresh_scripts:
__init__.py(156): if reload_scripts:
__init__.py(166): def register_module_call(mod):
__init__.py(179): def unregister_module_call(mod):
__init__.py(188): def test_reload(mod):
__init__.py(202): def test_register(mod):
__init__.py(215): if reload_scripts:
__init__.py(231): from bpy_restrict_state import RestrictBlend
--- modulename: bpy_restrict_state, funcname: <module>
bpy_restrict_state.py(23): """
bpy_restrict_state.py(26): "RestrictBlend",
bpy_restrict_state.py(29): import bpy as _bpy
bpy_restrict_state.py(32): class _RestrictContext:
--- modulename: bpy_restrict_state, funcname: _RestrictContext
bpy_restrict_state.py(32): class _RestrictContext:
bpy_restrict_state.py(33): __slots__ = ()
bpy_restrict_state.py(34): _real_data = _bpy.data
bpy_restrict_state.py(36): _real_pref = _bpy.context.user_preferences
bpy_restrict_state.py(38): @property
bpy_restrict_state.py(42): @property
bpy_restrict_state.py(47): class _RestrictData:
--- modulename: bpy_restrict_state, funcname: _RestrictData
bpy_restrict_state.py(47): class _RestrictData:
bpy_restrict_state.py(48): __slots__ = ()
bpy_restrict_state.py(51): _context_restrict = _RestrictContext()
bpy_restrict_state.py(52): _data_restrict = _RestrictData()
bpy_restrict_state.py(55): class RestrictBlend:
--- modulename: bpy_restrict_state, funcname: RestrictBlend
bpy_restrict_state.py(55): class RestrictBlend:
bpy_restrict_state.py(56): __slots__ = ("context", "data")
bpy_restrict_state.py(58): def __enter__(self):
bpy_restrict_state.py(64): def __exit__(self, type, value, traceback):
__init__.py(233): with RestrictBlend():
--- modulename: bpy_restrict_state, funcname: __enter__
bpy_restrict_state.py(59): self.data = _bpy.data
bpy_restrict_state.py(60): self.context = _bpy.context
bpy_restrict_state.py(61): _bpy.data = _data_restrict
bpy_restrict_state.py(62): _bpy.context = _context_restrict
__init__.py(234): for base_path in script_paths():
--- modulename: __init__, funcname: script_paths
__init__.py(306): scripts = list(_scripts)
__init__.py(308): if check_all:
__init__.py(314): base_paths = _bpy_script_paths()
__init__.py(316): for path in base_paths + (script_path_user(), script_path_pref()):
--- modulename: __init__, funcname: script_path_user
__init__.py(282): path = _user_resource('SCRIPTS')
__init__.py(283): return _os.path.normpath(path) if path else None
--- modulename: __init__, funcname: script_path_pref
__init__.py(288): path = _user_preferences.filepaths.script_directory
__init__.py(289): return _os.path.normpath(path) if path else None
__init__.py(317): if path:
__init__.py(318): path = _os.path.normpath(path)
__init__.py(319): if path not in scripts and _os.path.isdir(path):
__init__.py(320): scripts.append(path)
-- snip (around 40k lines) --