Skip to content

Instantly share code, notes, and snippets.

@odedlaz
Last active December 6, 2016 10:13
Show Gist options
  • Save odedlaz/1f5724ebac155af2714e1d2e01a0541b to your computer and use it in GitHub Desktop.
Save odedlaz/1f5724ebac155af2714e1d2e01a0541b to your computer and use it in GitHub Desktop.
optimzed_compile_print.py
import os
import six
from time import time
from random import choice
from string import Formatter
from string import ascii_letters
from inspect import currentframe
string_formatter = Formatter()
six.moves.builtins.std_print = print
def random_string(length=20):
"""
generate a random string of given length
"""
return "".join(choice(ascii_letters)
for _ in range(length))
class TextObject(object):
__slots__ = ["code", "locals", "globals"]
def __init__(self, caller, code):
self.code = code
self.locals = caller.f_locals
self.globals = caller.f_globals
@staticmethod
def get_keywords(text):
return {random_string(): kw for _, kw, _, _
in string_formatter.parse(text) if kw}
@classmethod
def from_text(cls, caller, text):
keywords = cls.get_keywords(text)
code = ["def awesome_print(text, **kwargs):"]
line_code = " {kw_name} = {kw_statement}"
for key, value in six.iteritems(keywords):
text = text.replace("{{{}}}".format(value),
"{{{}}}".format(key))
code.append(" text = \"{}\"".format(text))
args = ", ".join("{0}=({1})".format(key, val)
for key, val in six.iteritems(keywords))
print_line = " std_print(text.format({}), **kwargs)".format(args)
code.append(print_line)
return cls(caller=caller,
code="\n".join(code))
@classmethod
def compile(cls, caller, text):
# optimize for the trivial case where no formatting is done
if not cls.get_keywords(text):
return cls(code=std_print, caller=caller)
obj = cls.from_text(caller, text)
exec(obj.code, caller.f_locals, caller.f_locals)
return cls(code=caller.f_locals.pop("awesome_print"), caller=caller)
memoize = {}
def print(text, **kwargs):
text_obj = memoize.get(text)
if not text_obj:
frame = currentframe()
text_obj = TextObject.compile(text=text,
caller=frame.f_back)
memoize[text] = text_obj
# why delete the frame?
# https://docs.python.org/3/library/inspect.html#the-interpreter-stack
del frame
text_obj.code(text, **kwargs)
devnull = open(os.devnull, 'w')
name = "oded"
t = time()
for _ in range(50000):
print("my name is {name} & 2*3={2*3}", file=devnull)
std_print("block took {0:.3f} seconds".format(time() - t))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment