Created
December 12, 2017 13:25
-
-
Save cb109/b99c8d7c627e5238992b5f8a353c79c7 to your computer and use it in GitHub Desktop.
Python per-module excepthooks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from .hook import register_module_excepthook | |
from .hook import install_global_excepthook | |
def some_module_function_that_may_fail(): | |
raise ValueError("whoops!") | |
def module_excepthook(type_, value, tb): | |
print("Gosh, " + __name__ + " has produced an error!") | |
print(tb) | |
register_module_excepthook(__name__, module_excepthook) | |
# This must be called once somewhere in the application. | |
install_global_excepthook() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
sys.excepthook is global, meaning we can only define one at any given time. | |
Using the functions below we can make the global excepthook handle errors | |
differently based on the module filepath they came from, effectively giving | |
us per-module excepthooks. | |
""" | |
import os | |
import re | |
import sys | |
import traceback | |
from StringIO import StringIO | |
tb_file_regex = r'\"(?P<file>.+)\.py[cod]{0,1}\"' | |
file_regex = r'(?P<file>.+)\.py[cod]{0,1}' | |
_excepthook_registry = {} | |
def install_global_excepthook(): | |
sys.excepthook = _excepthook | |
def register_module_excepthook(module_name, func): | |
module = sys.modules[module_name] | |
module_file = os.path.abspath(module.__file__) | |
relevant_filename = re.match(file_regex, module_file).group("file") | |
_excepthook_registry[relevant_filename] = func | |
def _excepthook(type_, value, tb): | |
"""Assign this to sys.excepthook to handle per-module-hooks.""" | |
buf = StringIO() | |
traceback.print_tb(tb, file=buf) | |
matches = re.findall(tb_file_regex, buf.getvalue()) | |
if not matches: | |
return | |
culprit_filepath = matches[-1] | |
culprit_relevant_filename, _ = os.path.splitext(culprit_filepath) | |
hook = _excepthook_registry.get(culprit_relevant_filename) | |
if hook: | |
hook(type_, value, tb) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment