Python 程式碼精簡和優化

Python很簡單,容易使用,開發效率很高,移植性很好,程式碼資源也很豐富,被廣泛使用。但是Python程式碼編出來的動態庫比較大,python庫很全,缺點就是庫比較大。

在記憶體佔用方法,隨著py庫的引入,記憶體也成倍的增加,這裡來討論下如何來給Python瘦身,以及如何優化記憶體的佔用。

一、如何給Python的動態庫瘦身。

Python的程式碼還是很精練的,所以要減小小程式碼的大小比較困難,但是仍然有一些思路來減小Python庫的大小。

1、strip python動態庫。

動態庫一般都是包含符號表,這些在調用的時候很有用,但是對於release版本,完全可以把符號表去調,方法就是用strip命令,這樣大小可以從八九兆銳減到3兆以內。

2、使用程式碼優化選項:-O3,該參數會對程式碼進行最大程度的優化,包括優化生成的二進位程式碼的大小,缺點是優化後會對調試帶來困難。

3、去除程式碼中的Doc String.

Python的程式碼里有用PyDoc_STRVAR宏定義的模組的幫助說明,這些是可以去掉的,方法是在configure的時候指定–without-doc-strings,這樣生成的pyconfig.h中就會不會有下面的定義:

#define WITH_DOC_STRINGS 1

這可以減小生成的動態庫的大小,當然在運行時也可以減小模組的記憶體的佔用,因為這些模組不再包含幫助資訊。

4、去掉unicode支援。

python中unicode支援不是必需的,當然python 3另當別論。python中要支援unicode可以採用utf-8編碼的方式。去掉unicode的支援可以在configure的時候使用下面的參數:

–enable-unicode=no

這樣,在pyconfig.h中會去掉下面的定義:

#define Py_USING_UNICODE 1

二:如何減小Python的擴展庫的大小?

Python的擴展庫放在lib目錄下,可以在lib目錄下執行下面的命令來編譯Python程式碼:

python -OO -m compileall .

這樣會生成pyo擴展名的庫文件,-OO參數會去掉doc string,這樣在py文件中注釋比較多的時候可以顯著減小編譯目標文件的大小。

注意不要使用絕對路徑:

如python -OO -m compileall /path/to/python/lib 這樣使用絕對路徑的命令,因為生成pyo文件的時候,,每個函數和類的方法會生成一個一個的code object對象,每個code object都會保存它所在的模組的路徑,如果使用絕對路徑,在路徑比較長的時候,函數又比較多的時候,很顯著的增加pyo文件的大小。

當然,在程式碼運行時,也可以減小記憶體的佔用量。

三、如何裁減擴展庫。

有個py2exe的工具可以打包python程式碼和依賴的動態庫,把python所必須的擴展庫打包到zip文件中,但是實際上這個zip包往往並不是最精簡的。其實裁減的最大難點是要找出所有依賴的模組,可以用下面的方法來找出某個模組所依賴的其它模組:

import importlib  def module_diff(mod):      import sys      keys = []      for key in sys.modules.keys():          keys.append(key)      importlib.import_module(mod)      for key in sys.modules.keys():          if not key in keys:              print key,sys.modules[key]

如要查看multiprocessing模組所依賴的模組,可以用下面的命令:

module_diff('multiprocessing')

將會得到下面的輸出:

multiprocessing.atexit None  multiprocessing.weakref None  multiprocessing.signal None  threading <module 'threading' from 'C:Python27libthreading.pyc'>  cPickle <module 'cPickle' (built-in)>  _multiprocessing <module '_multiprocessing' from 'C:Python27DLLs_multiprocessing.pyd'>  multiprocessing.os None  multiprocessing.itertools None  multiprocessing.threading None  multiprocessing.util <module 'multiprocessing.util' from 'C:Python27libmultiprocessingutil.pyc'>  multiprocessing.sys None  cStringIO <module 'cStringIO' (built-in)>  multiprocessing._multiprocessing None  multiprocessing.multiprocessing None  thread <module 'thread' (built-in)>  atexit <module 'atexit' from 'C:Python27libatexit.pyc'>  multiprocessing <module 'multiprocessing' from 'C:Python27libmultiprocessing__init__.pyc'>  weakref <module 'weakref' from 'C:Python27libweakref.pyc'>  itertools <module 'itertools' (built-in)>  time <module 'time' (built-in)>  multiprocessing.process <module 'multiprocessing.process' from 'C:Python27libmultiprocessingprocess.pyc'

這樣就可以知道所依賴的模組了。

 要查看所有的模組,則更簡單:

def print_all_module():      import sys      keys = []      for key in sys.modules.keys():          print key,sys.modules[key]

在程式碼初始化完後執行上面的函數,就可以知道程式運行所需的模組了。