我有一些python代碼:
- 從不同端點提取各種指標
- 用一些標準化的鍵/值將它們加入到一個通用字典中
- 將字典上傳到另一個工具進行分析
雖然這通常有效,但當字典變得太大時會出現問題,它會導致各個方面的性能問題。
我已經看到使用 itertools 根據鍵范圍進行拆分,根據鍵數均勻拆分的示例。但是,我想嘗試根據位元組大小對其進行拆分,因為某些指標比其他指標大得多。
可以根據位元組大小將字典動態拆分為字典串列嗎?
uj5u.com熱心網友回復:
假設鍵和值都是可以sys.getsizeof以有意義的方式呼叫的合理型別以及所有不同的物件,您可以使用該資訊將字典拆分為相等的塊。
如果您希望最大塊成為其除數,請首先計算總大小。如果您的最大尺寸在外部是固定的,則可以跳過此步驟:
total_size = sum(getsizeof(k) getsizeof(v) for k, v in my_dict.items())
max_size現在您可以迭代字典,假設整個字典的大小大致隨機分布,在超過閾值之前剪切一個新字典:
from sys import getsizeof
def split_dict(d, max_size):
result = []
current_size = 0
current_dict = {}
while d:
k, v = d.popitem()
increment = getsizeof(k) getsizeof(v)
if increment current_size > max_size:
result.append(current_dict)
if current_size:
current_dict = {k: v}
current_size = increment
else:
current_dict[k] = v # going to list
current_dict = {}
current_size = 0
else:
current_dict[k] = v
current_size = increment
if current_dict:
result.append(current_dict)
return result
請記住,這dict.popitem是具有破壞性的:您實際上是在洗掉所有內容my_dict以填充較小的版本。
這是一個高度簡化的示例:
>>> from string import ascii_letters
>>> d = {s: i for i, s in enumerate(ascii_letters)}
>>> total_size = sum(getsizeof(k) getsizeof(v) for k, v in d.items())
>>> split_dict(d, total_size // 5)
[{'Z': 51, 'Y': 50, 'X': 49, 'W': 48, 'V': 47, 'U': 46, 'T': 45, 'S': 44, 'R': 43, 'Q': 42},
{'P': 41, 'O': 40, 'N': 39, 'M': 38, 'L': 37, 'K': 36, 'J': 35, 'I': 34, 'H': 33, 'G': 32},
{'F': 31, 'E': 30, 'D': 29, 'C': 28, 'B': 27, 'A': 26, 'z': 25, 'y': 24, 'x': 23, 'w': 22},
{'v': 21, 'u': 20, 't': 19, 's': 18, 'r': 17, 'q': 16, 'p': 15, 'o': 14, 'n': 13, 'm': 12},
{'l': 11, 'k': 10, 'j': 9, 'i': 8, 'h': 7, 'g': 6, 'f': 5, 'e': 4, 'd': 3, 'c': 2},
{'b': 1, 'a': 0}]
如您所見,拆分在分布方面不一定是最佳的,但它確保沒有塊大于max_size,除非單個條目需要更多位元組。
更新不健全的價值觀
如果您有任意大的嵌套值,您仍然可以在頂層拆分,但是,您必須getsizeof(v)用更健壯的東西替換。例如:
from collections.abc import Mapping, Iterable
def xgetsizeof(x):
if isinstance(x, Mapping):
return getsizeof(x) sum(xgetsizeof(k) xgetsizeof(v) for k, v in x.items())
if isinstance(x, Iterable) and not isintance(x, str):
return getsizeof(x) sum(xgetizeof(e) for e in x)
return getsizeof(x)
現在您還可以通過total_size一次呼叫進行計算:
total_size = xgetsizeof(d)
請注意,這比您之前看到的值大。之前的結果是
xgetsizeof(d) - getsizeof(d)
為了使解決方案真正健壯,您需要添加實體跟蹤以避免回圈參考和重復計算。
我繼續為我的庫haggis撰寫了這樣一個函式,稱為haggis.objects.getsizeof. 它的行為與xgetsizeof上面大致相似,但更加穩健。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/417542.html
標籤:
