如何将多个Python源文件合并为一个文件?
(假设:应用程序的启动时间非常关键;我的应用程序启动频繁;我的应用程序运行在一个导入速度比平常慢的环境中;需要导入很多文件;并且不能编译成 .pyc
文件。)
我想把所有定义了一组模块的 Python 源文件合并成一个新的 Python 源文件。
我希望导入这个新文件的效果就像我导入其中一个原始文件一样(然后这个原始文件会再导入其他一些原始文件,依此类推)。
这样做可能吗?
下面是一个粗略的手动模拟,展示了一个工具在处理模块 'bar' 和 'baz' 的源文件时可能产生的结果。你会在部署代码之前运行这样的工具。
__file__ = 'foo.py'
def _module(_name):
import types
mod = types.ModuleType(name)
mod.__file__ = __file__
sys.modules[module_name] = mod
return mod
def _bar_module():
def hello():
print 'Hello World! BAR'
mod = create_module('foo.bar')
mod.hello = hello
return mod
bar = _bar_module()
del _bar_module
def _baz_module():
def hello():
print 'Hello World! BAZ'
mod = create_module('foo.bar.baz')
mod.hello = hello
return mod
baz = _baz_module()
del _baz_module
现在你可以:
from foo.bar import hello
hello()
这段代码没有考虑像导入语句和依赖关系这样的东西。有没有现成的代码可以用来通过这种方式,或者其他技术来组合源文件?
这个想法和一些工具在发送 JavaScript 文件到浏览器之前进行组合和优化的方式非常相似,因为多个 HTTP 请求的延迟会影响性能。在这个 Python 的例子中,问题在于启动时导入数百个 Python 源文件的延迟会造成影响。
4 个回答
这样做不太可能带来性能上的提升。你仍然是在导入相同数量的Python代码,只是模块变少了而已——而且你为了这个牺牲了模块化的好处。
更好的方法是修改你的代码和/或库,只在需要的时候导入东西,这样每次请求时只加载最少的必要代码。
我觉得因为Python文件在运行之前会被预编译,还有一些系统缓存的原因,你最终得到的速度提升是很难被测量出来的。
如果你在使用谷歌应用引擎(Google App Engine),那么请确保你使用了这个方法。
def main():
#do stuff
if __name__ == '__main__':
main()
因为谷歌应用引擎不会在每次请求时重启你的应用,除非你的.py文件有变化,它只是再次运行 main()
函数。
这个技巧可以让你写出类似CGI风格的应用,而不会因为启动而影响性能。
如果一个处理脚本提供了一个 main() 函数,运行环境会缓存这个脚本。否则,每次请求时都会加载这个处理脚本。