Last active
December 6, 2016 10:13
-
-
Save odedlaz/1f5724ebac155af2714e1d2e01a0541b to your computer and use it in GitHub Desktop.
optimzed_compile_print.py
This file contains hidden or 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
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