Skip to content

Instantly share code, notes, and snippets.

@L3viathan
Created July 29, 2022 10:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save L3viathan/e93f8c9f2b000a0963c3adadcb5b9d92 to your computer and use it in GitHub Desktop.
Save L3viathan/e93f8c9f2b000a0963c3adadcb5b9d92 to your computer and use it in GitHub Desktop.
Go-like defer statements
import sys
import inspect
from contextlib import contextmanager
from collections import defaultdict
deferred_lines = defaultdict(list)
def defer_trace(frame, event, arg):
if event != "line":
return defer_trace
with open(inspect.getsourcefile(frame)) as f:
lines = f.readlines()
line = lines[frame.f_lineno - 1].strip()
if line.startswith("defer; "):
deferred_lines[frame].append(line.strip()[len("defer; "):])
frame.f_lineno += 1
else:
pass
return defer_trace
@contextmanager
def deferable():
frame = sys._getframe().f_back.f_back
sys.settrace(lambda *a:None)
frame.f_trace = defer_trace
try:
yield
finally:
for line in reversed(deferred_lines[frame]):
exec(line, frame.f_globals, frame.f_locals)
deferred_lines.pop(frame)
sys.settrace(None)
with deferable():
print("Hello")
defer; print("Bye")
print("Middle")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment