Python 代碼精簡和優化

jopen 9年前發布 | 24K 次閱讀 Python 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]  
</div> </div>
如要查看multiprocessing模塊所依賴的模塊,可以用下面的命令:
    module_diff('multiprocessing')  


將會得到下面的輸出:

    multiprocessing.atexit None  
    multiprocessing.weakref None  
    multiprocessing.signal None  
    threading <module 'threading' from 'C:\Python27\lib\threading.pyc'>  
    cPickle <module 'cPickle' (built-in)>  
    _multiprocessing <module '_multiprocessing' from 'C:\Python27\DLLs\_multiprocessing.pyd'>  
    multiprocessing.os None  
    multiprocessing.itertools None  
    multiprocessing.threading None  
    multiprocessing.util <module 'multiprocessing.util' from 'C:\Python27\lib\multiprocessing\util.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:\Python27\lib\atexit.pyc'>  
    multiprocessing <module 'multiprocessing' from 'C:\Python27\lib\multiprocessing\__init__.pyc'>  
    weakref <module 'weakref' from 'C:\Python27\lib\weakref.pyc'>  
    itertools <module 'itertools' (built-in)>  
    time <module 'time' (built-in)>  
    multiprocessing.process <module 'multiprocessing.process' from 'C:\Python27\lib\multiprocessing\process.pyc'  
</div> </div>

 

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

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

    def print_all_module():  
        import sys  
        keys = []  
        for key in sys.modules.keys():  
            print key,sys.modules[key]  
</div> </div>
在代碼初始化完后執行上面的函數,就可以知道程序運行所需的模塊了。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!