I am playing around with building my own back end with python 2.7 and jinja2/cgi. Originally I was defining some of my environment and loader variables at the top but figured this was not the best practice. I then defined functions for each, but they'd only get called once or twice depending on which route it decided to execute. I came up with this class idea instead that I pass into my dispatch function, which in turn passes it into whatever rendering function happens to be being executed. Is this the proper 'pythonic' way to approach having a template loader, and if not would anyone have any suggestions?

class Template(object):
def __init__(self):
self._environment = None

def __call__(self, temp_name):
return self.get_env.get_template(temp_name)

@property
def get_env(self):
return self._environment

@get_env.getter
def get_env(self):
if not self._environment:

return self._environment


This class then allows me to just call template('templateFileName.j2') and be returned that jinja template object. If the environment is not created, the getter will create one for me.

For starter, I'd rewrite get_env a bit and introduce intermediate variables for readability:

def get_env(self):
if not self._environment:
cwd = os.path.dirname(os.path.abspath(__file__))
return self._environment


Next I would cleanup your @property usage; since the raw decorator already defines the getter property, you can get rid of the first method:

class Template(object):
def __init__(self):
self._environment = None

def __call__(self, temp_name):
return self.get_env.get_template(temp_name)

@property
def get_env(self):
if not self._environment:
cwd = os.path.dirname(os.path.abspath(__file__))
return self._environment


Lastly, since the initialization of _environment is meant to be done (and thus checked) only once, why not take advantage of attribute access that already offer us this kind of flexibility:

class Template(object):
def __call__(self, temp_name):
return self.environment.get_template(temp_name)

def __getattr__(self, attribute):
if attribute == 'environment':
cwd = os.path.dirname(os.path.abspath(__file__))
return env
return super(Template, self).__getattr__(attribute)


This way, __getattr__ is only called the first time self.environment is accessed and never again. But... Hold on... The only usefull method of this class is __call__... Better write a function instead; this will bring the check back at each call but will make the intent clearer:

def load_template(template_name):
cwd = os.path.dirname(os.path.abspath(__file__))


So now, no need to pass an object around everywhere, just call the function when you need to.

And if you want to, EAFP can also help reduce the overhead of the hasattr test:

def load_template(template_name):
try:
except AttributeError:
cwd = os.path.dirname(os.path.abspath(__file__))

• @Turk Not sure about what you are trying to do. Running multiple instances of python (even in parallel) is not at all the same thing than running several threads into the same script. You don't have to consider concurency in the first case as each invocation will have to initialize an environment anyway; but in the second case you might need it. The lock I was thinking about comes from the threading module and is not really needed if you don't use anything from it. Mar 6 '17 at 22:10