Python記憶體管理指南
- 2019 年 11 月 27 日
- 筆記
原標題 | Memory Management in Python
作 者 | Jun Wu
翻 譯 | 天字一號
審 校 | 唐里、Pita
對於軟體開發人員而言,了解記憶體管理很重要。隨著Python在軟體開發中得到廣泛使用,編寫高效的Python程式碼通常意味著需要編寫記憶體高效使用的程式碼。隨著大數據的使用越來越廣泛,記憶體管理的重要性不容忽視。無效的記憶體管理會導致應用程式和伺服器端組件運行緩慢。記憶體泄漏通常會導致花費大量時間進行測試和調試,它還會嚴重破壞數據處理並引起並發處理問題。
即使大多數Python的記憶體管理都是由Python記憶體管理器完成的,但了解最佳編碼實踐以及Python的記憶體管理器的工作方式仍可以使程式碼更高效和可維護。
對於軟體開發人員而言,記憶體管理最重要的部分是記憶體分配。了解在電腦的物理或虛擬記憶體中分配空白空間的過程至關重要。有兩種類型的記憶體分配。
靜態記憶體分配 – 程式在編譯時分配了記憶體。例如在C / C ++中,您只能聲明具有固定大小的靜態數組。在編譯時分配記憶體。堆棧用於實現靜態分配。在這種情況下,不能重用記憶體。
static int a=10;
動態記憶體分配 – 在運行時為程式分配了記憶體。例如,在C / C ++中,您可以使用一元運算符new聲明數組。記憶體在運行時分配。堆用於實現動態分配。在這種情況下,不需要時可以釋放和重用記憶體。
int *p; p=new int;
關於Python的好處是Python中的所有東西都是對象。這意味著動態記憶體分配是Python記憶體管理的基礎。當不再需要對象時,Python記憶體管理器將自動從它們中回收記憶體。
Python是使用C程式語言實現的高級程式語言。Python記憶體管理器管理Python的記憶體分配。有一個私有heap,其中包含所有Python對象和數據結構。Python記憶體管理器按需管理Python堆。Python記憶體管理器具有特定於對象的分配器,可為int,string等特定對象分別分配記憶體。在此之下,原始記憶體分配器與作業系統的記憶體管理器進行交互,以確保私有堆上有空間。
Python記憶體管理器管理稱為「塊」的記憶體塊。相同大小的塊的集合構成了「池」。池是在Arenas上創建的,在堆= 64池上分配了256kB的記憶體塊。如果對象被銷毀,則記憶體管理器將用相同大小的新對象填充此空間。
方法和變數在堆棧存儲器中創建。每當創建方法和變數時,都會創建一個堆棧框架。只要返回方法,這些框架就會自動銷毀。
在堆記憶體中創建對象和實例變數。一旦返回變數和函數,將對垃圾對象進行垃圾回收。
請務必注意,Python記憶體管理器不一定會將記憶體釋放回作業系統,而是將記憶體返回給python解釋器。Python有一個小的對象分配器,用於分配記憶體以供進一步使用。在長時間運行的進程中,您可能有未使用記憶體的增量保留。
使用聯接將項目添加到列表是高效Python程式碼的最佳做法
無需將line1,line2分別添加到mymsg,而是使用list和join。
不要這樣:
mymsg=』line1n』 mymsg+=』line2n』
最好這樣:
mymsg=[『line1』,』line2'] 『n』.join(mymsg)
避免對字元串使用+運算
如果可以避免,請不要使用+運算符進行串聯。由於字元串是不可變的,因此每次將元素添加到字元串時,Python都會創建一個新的字元串和一個新的地址。這意味著每次更改字元串時都需要分配新的記憶體。
不要這樣做:
msg=』hello』+mymsg+』world』
更好的選擇:
msg=』hello %s world』 % mymsg
使用Generators
生成器允許您創建一個函數,一次返回一個項目,而不是一次返回所有項目。這意味著,如果您有大型數據集,則不必等待整個數據集都可以訪問。
def __iter__(self): return self._generator() def _generator(self): for itm in self.items(): yield itm
將評估置於循環之外
如果要遍曆數據,則可以使用正則表達式的快取版本。
match_regex=re.compile(「foo|bar」) for i in big_it: m = match_regex.search(i) ….
將函數分配給局部變數
Python訪問局部變數要比全局變數有效得多。將函數分配給局部變數,然後使用它們。
myLocalFunc=myObj.func for i in range(n): myLocalFunc(i)
使用內置函數和庫
儘可能使用內置函數和庫。內置函數通常使用最佳記憶體使用方法來實現。
不要這樣做:
mylist=map(str.lower, oldlist)
與循環相比,使用關鍵字參數創建數據集的更好選擇:
mycounter = Counter (a = 1, b = 2, c = 3, d = 5, e = 6, f = 7, g = 8) for i in mycounter.elements()
通過使用itertools擺脫不必要的循環
itertools(https://docs.python.org/3/library/itertools.html)為您節省了大量的循環時間。它還擺脫了程式碼的複雜性。
不要這樣做:
mylist=[] for shape in [True, False]: for weight in (1, 5): firstlist=firstlist+function(shape, weight)
最好這樣:
from itertools import product, chain list(chain.from_iterable(function(shape, weight) for weight, shape in product([True, False], range(1, 5))))
覆蓋_new_並利用元類來進行安全和記憶體管理——作者@maxwell flitton
重寫_new_並利用元類進行安全和記憶體管理,方法是@maxwell flitton 在執行Singleton和Flyweight模式時,重寫__new__並利用元類對記憶體管理也非常有用和安全。例如,這是一個讀取Yaml文件的dict對象的示例。因為它的元類一經定義便是單例設計模式,因此可以將其導入系統中的任何位置並再次定義,並且解釋器將僅指向初始對象。它減少了記憶體佔用並確保了安全性。不管團隊中的其他開發人員多麼初級,它們都不會導致重複的對象,從而防止它們更改系統某一部分中的命令,並防止另一部分中引用另一條命令。
class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class ConfigDict(dict, metaclass=Singleton): def __init__(self): super().__init__(self.read_config_file()) @staticmethod def read_config_file(): 「」」 Reads config file based on path passed when running app. :return: (dict) loaded data from yml file 「」」 config_file_path = sys.argv[-1] if not config_file_path.endswith(「.yml」): raise ConfigDictError(message=」yml file not passed into flask app but {} instead」.format(config_file_path)) return yaml.load(open(str(config_file_path)), Loader=yaml.FullLoader)
如何檢查Python程式碼的性能
您可以使用配置文件模組(例如cProfile和Profile:https://docs.python.org/3/library/profile.html)進行性能檢查。
python -m cProfile [-o output_file][-s sort_order](-m module | myscript.py)
閱讀有關Python記憶體管理的更多資訊,可查看以下資源:
- 流利的Python:清晰,簡潔,有效的編程(http://geni.us/xA2PP)
- Python Cookbook:精通Python 3(http://geni.us/yAoO1S)
- 真正的Python:Python中的記憶體管理(https://realpython.com/python-memory-management/)
- Python.org記憶體管理(https://docs.python.org/3/c-api/memory.html)
- Atem Golubin:Python中的記憶體管理(https://rushter.com/blog/python-memory-managment/)


