像这样隐藏进口是一种优化;每当考虑是否优化时,验证提议的优化是否真的有效。
我们首先考虑datetime
的具体示例。这里有一个简单的应用程序:
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)])
如果我们参观“/”的网址,我们看到这样的输出:
datetime模块已经加载。
706模块已经载入
95标准库模块已经载入
207的AppEngine模块已经载入
即使在这个最小的应用程序,datetime
已经由SDK进口*。一旦Python导入了一个模块,进一步的导入只花费一次字典查找,所以隐藏导入没有任何好处。由于SDK已经导入了95个标准库模块和207个SDK模块,因此隐藏导入常用标准库或SDK模块的可能性不大。
这留下了导入应用程序代码的问题。处理程序可以延迟加载通过声明他们作为路线字符串,这样直到路线参观他们没有进口:
app = webapp2.Application([('/foo', 'handlers.FooHandler')])
这种技术允许优化启动时间不隐藏在类或方法的进口,你应该找这是必要的。
其他答案指出,延迟加载的代价可能是意外的运行时错误。此外,如果您选择隐藏导入,它也会降低代码可读性,可能导致结构性问题,例如掩盖循环依赖性,并为经验较少的开发人员设置一个不好的示例,他们可能会认为隐藏导入是惯用的而不是优化。
因此,考虑以这种方式优化时:
- 验证优化是必要的:不是所有的应用程序都需要绝对最大性能
- 验证正确的问题正在得到解决;在App Engine上的RPC调用往往主宰响应时间
- 配置文件以验证优化是有效
- 考虑代码的可维护性
*费用依托SDK的sys.modules
是相似的我希望云运行时是一个合理的假设。