Hiding imports like this is an optimisation; whenever considering whether to optimise, verify that the proposed optimisation is really going to be effective.
Let's consider the specific example of datetime
first. Here's a simple app:
import sys
import webapp2
class Handler(webapp2.RequestHandler):
def get(self):
if 'datetime' in sys.modules:
self.response.write('The datetime module is already loaded.\n')
else:
self.response.write('The datetime module is not already loaded\n.')
self.response.write('%d modules have been loaded\n' % len(sys.modules))
count = sum(1 for x in sys.modules.values() if '/lib64' in repr(x))
self.response.write('%d standard library modules have been loaded\n' % count)
gcount = sum(1 for x in sys.modules.values() if 'appengine' in repr(x))
self.response.write('%d appengine modules have been loaded\n' % gcount)
application = webapp2.WSGIApplication([('/', Handler)])
If we visit the '/' url we see this output:
The datetime module is already loaded.
706 modules have been loaded
95 standard library modules have been loaded
207 appengine modules have been loaded
Even in this minimal app, datetime
has already been imported by the SDK*. Once Python has imported a module, futher imports only cost a single dictionary lookup, so there is no benefit in hiding the import. Given that the SDK has already imported 95 standard library modules and 207 SDK modules it follows that there is unlikely to be much benefit in hiding imports of commonly used standard library or SDK modules.
This leaves the question of imports of application code. Handlers can be lazy-loaded by declaring them as strings in routes, so that they are not imported until the route is visited:
app = webapp2.Application([('/foo', 'handlers.FooHandler')])
This technique permits optimising startup time without hiding imports in classes or methods, should you find that it is necessary.
The cost of lazy-loading, as the other answers point out, can be unexpected runtime errors. Moreover, if you choose of hide imports it can also decrease code readability, potentially cause structural problems, for example masking circular dependencies, and sets a poor example for less experienced developers, who may assume that hiding imports is idiomatic rather than an optimisation.
So, when considering optimising in this way:
- verify that optimisation is necessary: not all applications require absolute maximum performance
- verify that the right problem is being addressed; RPC calls on App Engine tend to dominate response times
- profile to verify that the optimisation is effective
- consider the costs in code maintainability
*Relying on the SDK's sys.modules
being similar to that of the cloud runtime is, I hope, a reasonable assumption.