天天看點

持久化 Python 會話:實作資料持久化和可重用性

作者:新語資料故事彙
持久化 Python 會話:實作資料持久化和可重用性

Midjourney 生成

R語言會話持久化

  熟悉或常用R語言進行資料分析/資料挖掘/資料模組化的資料工作者可能對R語言的會話儲存和會話恢影印象比較深刻,它可以将目前session會話持久化儲存,以便分享給其他人開展後續的分析工作,而不需要重新執行前面的内容(前面資料處理過程可能很費時間),進而大大降低處理時間并提升效率。

  RData 檔案和 save.image() 函數的核心意義是提供一種友善的方式來儲存和加載 R 會話的工作空間。它們的核心意義有以下幾點:

  1. 持久化工作空間:RData 檔案和 save.image() 函數允許你将目前會話的工作空間儲存到硬碟上的檔案中。這樣,你可以在不同的時間點或不同的計算機上恢複儲存時的工作環境。這對于長期項目、複雜分析和需要重複運作相同代碼的情況非常有用。你可以儲存資料、函數、變量和其他對象,以便将來使用。
  2. 環境共享和遷移:通過儲存和加載工作空間,你可以友善地共享代碼和資料,并在不同的 R 會話之間共享環境。這對于團隊合作、結果複現和共享分析成果非常有幫助。你可以将工作空間發送給其他人,或在不同的計算機之間遷移工作環境,而無需手動重新建立對象和設定環境。
  3. 提高工作效率:RData 檔案和 save.image() 函數可以幫助你節省時間和努力。你可以将工作空間儲存為檔案,避免在每次啟動 R 會話時重新加載資料和設定環境。這樣,你可以快速回到之前的工作狀态,繼續進行分析或開發,而不必從頭開始。

  總而言之,RData 檔案和 save.image() 函數的核心意義是提供一種簡單而有效的方法來儲存和加載 R 會話的工作空間,以友善地保留和共享環境,節省時間并提高工作效率。

Python會話如何持久化?

  持久化和恢複Python 對大資料處理(Data PipeLine)架構由比較大意義。

  大資料應用的典型範式是由資料管道(Data PipeLine)組成的一系列資料加工處理和應用的過程,主流資料管道處理架構如批處理、流處理管道和Lambda架構。在這些資料管道中,Python 在資料處理和應用方面的應用越來越廣泛,并成為主流的計算方式。Python 可以用于控制批處理部分的邏輯控制(與資料平台互動),并很好地支援互動資料應用部分,如互動報表和算法模型的預測服務。整個過程可以分為兩部分:批處理部分(資料加工過程)和互動資料應用部分。

  關于這兩部分如何更好地結合,有兩種方式:

  • 分離方式:在這種方式下,批處理部分和互動資料應用部分是互相分離的。批處理部分負責資料加工和持久化,将結果存儲在資料庫或其他持久化資料存儲中。互動資料應用部分則從持久化資料中加載所需的資料,并進行互動式應用和分析。這種方式可以通過資料庫查詢或資料加載方式來關聯兩部分的資料。
  • 統一方式:在這種方式下,整個過程是統一和一體的。批處理部分的結果會被持久化,然後互動資料應用部分加載批處理結果的會話(session),并進行互動式的應用。這種方式可以通過使用适當的工具和架構,如dill等,來實作會話的持久化和加載。
持久化 Python 會話:實作資料持久化和可重用性

  那如何在Python中實作類似于 R 的 save.image() 功能,将會話資料持久化,以便在需要時重新加載和重用?

接下來介紹一下筆者嘗試使用dill 包實作session會話的儲存和恢複,同時修複dill在Notebook中使用出現的bug。

關于dill

  dill 是一個擴充了 Python 的 pickle 子產品的庫,用于序列化和反序列化 Python 對象,并具有儲存解釋器會話狀态的功能。

  GitHub位址:https://github.com/uqfoundation/dill

主要功能:

  a. 序列化和反序列化 Python 對象到大多數内置 Python 類型。

  b. 提供與 pickle 子產品相同的使用者界面,并具有一些附加功能。

  c. 能夠儲存解釋器/Kernel會話的狀态,以便在不同的解釋器/Kernel會話之間恢複和繼續執行。

  d. 可以将 Python 對象作為位元組流發送到網絡上。

  e. 允許對任意使用者定義的類和函數進行序列化。

  f. dill 是 pathos(pathos 是一個并行計算和多核程式設計的架構,旨在簡化在多個計算資源上執行任務的過程。它提供了一組工具和接口,使得在分布式和并行計算環境中編寫高效的代碼更加容易) 架構的一部分,用于異構計算。

dill操作執行個體

  • 安裝dill
pip install dill
           
  • 定義變量
import pandas as pd
import numpy as np
a=[100,'aa']
b={"x":100,"y":'200'}
df1 = pd.DataFrame({'A': np.arange(1,1000), 'B': np.arange(2,1001)})
df1
           
  • 儲存session 會話
import dill
filepath = 'session1.pkl'
dill.dump_module(filename=filepath)
           
  • 關閉python 或kernel
  • 重新進入python或重新開機kernel,加載session:
import dill
filepath = 'session1.pkl'
dill.load_module(filename=filepath) 
df1
           
持久化 Python 會話:實作資料持久化和可重用性

dill 在notebook上執行個體

  通過測試發現,dill 在notebook上執行dump_module失敗,經過排查主要由于IPython和ipykernel 相關socket對象無法持久化導緻異常。IPython和ipykernel 主要kernel 與notebook 通信互動的相關包和對象,建立kernel 會自動生成無需持久化和恢複。

持久化 Python 會話:實作資料持久化和可重用性

  經排查和閱讀dill 源代碼,可以使用register重新注冊dict 持久化類,先預處理過濾掉相關對象,再調用dill 内部snb_save_module_dict。代碼參考如下:

from dill._dill import register
from dill._dill import save_module_dict
"""
dill 在notebook 裡面無法正常使用,由于IPython和ipykernel 相關socket對象無法持久化,save pickl 時候需要過濾掉相關對象。
register 重新注冊dict 持久化類,先預處理過濾掉,再調用dill 内部snb_save_module_dict。
"""
@register(dict)
def snb_save_module_dict(pickler, obj):
  keys=list(obj.keys())
  for k in keys:
    if type(obj[k]).__module__.startswith("ipykernel.") or type(obj[k]).__module__.startswith("IPython."):
      obj.pop(k,None)
    else:
      pass
      #print(k,obj[k])
  save_module_dict(pickler, obj)
           

經過測試,dill 可以完整在Notebook 使用。

持久化 Python 會話:實作資料持久化和可重用性