全部產品
Search
文件中心

:PyODPS DataFrame的代碼運行環境

更新時間:Feb 28, 2024

使用PyODPS DataFrame編寫資料應用時,同一個指令檔中的代碼會在不同位置執行,可能導致一些無法預期的問題,本文為您介紹當出現相關問題時,如何確定代碼的執行環境,以及提供部分情境下的解決方案。

概述

PyODPS是一個Python包而非Python Implementation,其運行環境均為未經修改的Python,因而並不會出現與正常Python解譯器不一致的行為。即您所編寫的每一條語句都與標準Python語句行為相同,例如自動變成分布式代碼等。

  • 程式碼範例

    from odps import ODPS, options
    import numpy as np
    
    o = ODPS(...)
    df = o.get_table('pyodps_iris').to_df()
    
    coeffs = [0.1, 0.2, 0.4]
    
    def handle(v):
        import numpy as np
        return float(np.cosh(v)) * sum(coeffs)
    
    options.df.supersede_libraries = True
    val = df.sepal_length.map(handle).sum().execute(libraries=['numpy.zip', 'other.zip'])
    print(np.sinh(val))
  • 代碼執行系統

    下圖是上述代碼執行時可能涉及的系統。代碼本身執行的系統都位於MaxCompute外部,為了方便表述,下文統稱為本地image.png

  • 程式碼分析

    • 引用第三方包

      在本地執行的程式碼封裝括handle函數之外的部分(注意handle傳入map時僅傳入了函數本身而並未執行)。因而,這些代碼在執行時,行為與普通Python code的執行行為類似,匯入第三方包時,引用的是本地的包。上述代碼中,libraries=['numpy.zip', 'other.zip']中引用的other.zip因為並沒有在本地安裝,如果代碼中有諸如import other的語句,則會導致執行報錯。即便other.zip已被上傳至MaxCompute資源也是如此,因為本地不存在other.zip包。理論上,本地代碼如果不涉及PyODPS包,則與PyODPS無關,執行報錯時您需要自行排查。

    • handle函數

      handle函數傳入map方法時,如果使用的後端是MaxCompute後端,會經歷以下幾個階段:

      1. 會先被cloudpickle模組提取閉包和位元組碼

      2. PyODPS DataFrame使用閉包和位元組碼產生一個Python UDF,提交至MaxCompute。

      3. 作業以SQL的形式在MaxCompute執行時,會調用已產生的Python UDF,其中的位元組碼和閉包內容會被unpickle(還原序列化),然後在MaxCompute Executor執行。

    • 總結

      • handle函數體中的代碼都不會在本地執行,而是在MaxCompute Executor中執行。

      • handle函數體中無法引用本地安裝的包,只有在MaxCompute Executor中存在的包才有效。

      • 上傳的第三方包必須能夠在MaxCompute Executor的Python版本(目前為Python 2.7,UCS2)中調用。

      • handle函數體中修改引用的外部變數(例如上述代碼中的coeffs)不會導致本地的coeffs值被修改。

      • 如果在handle函數體中引用在handle外import的包可能會報錯,因為在不同環境中,包的結構可能不同,而cloudpickle會將當地套件的引用代入MaxCompute Executor,導致報錯,因而建議import在handle函數體中進行。

      • 由於使用cloudpickle,如果在handle函數體中調用了其他檔案的代碼,該檔案所在的包必須存在於MaxCompute Executor中。如果您不想使用第三方包的形式解決該問題,請將所有引用的個人代碼放在同一個檔案中。

上述handle函數的解釋對於自訂彙總、apply和map_reduce中調用的自訂方法/Agg類均適用。如果使用的後端是Pandas後端,則所有代碼都會在本地運行,因而本地也需要安裝相關的包。但鑒於Pandas後端調試完畢後通常會轉移到MaxCompute運行,建議在本地安裝包的同時,參照MaxCompute後端的慣例進行開發。

使用第三方包

  • 個人電腦/自有伺服器:在本地使用第三方包或其他檔案中的代碼時,在相應的Python版本上安裝即可。

  • Notebook:在本地代碼中使用第三方包或其他檔案中的代碼請諮詢平台提供方。

  • DataWorks:DataWorks不支援在本地安裝第三方包,但可以進行調用。對於其他檔案中的代碼,可以通過讀取檔案+exec命令的方式在本地進行使用。詳情請參見在PyODPS節點中調用第三方包

    重要
    • DataStudio中的目錄結構並非檔案系統中真實存在的目錄結構,直接import或開啟DataStudio中顯示的檔案路徑會導致執行失敗。

    • 在DataWorks中上傳資源後,需要點擊提交確保資源被正確上傳到ODPS。

    • 如果需要使用自己的Numpy版本,在上傳正確的wheel包的同時,需要配置odps.df.supersede_libraries = True,同時確保您上傳的Numpy包名作為libraries的第一個參數。

引用其他MaxCompute表中的資料

  • 個人電腦/自有伺服器:在本地訪問MaxCompute表,如果Endpoint可以串連,使用PyODPS/DataFrame訪問。

  • Notebook/DataWorks:在本地代碼中訪問MaxCompute表,如果Endpoint可以串連,使用PyODPS/DataFrame訪問。串連Endpoint時出現問題請諮詢平台提供方。

  • map/apply/map_reduce/自訂彙總:訪問其他MaxCompute表,MaxCompute Executor中通常不支援訪問Endpoint/Tunnel Endpoint,也沒有PyODPS包可用,因而不能直接使用ODPS入口對象或者PyODPS DataFrame,也不能從自訂函數外部傳入這些對象。如果表的資料量不大,建議將DataFrame作為資源傳入,詳情請參見引用資源。如果資料量較大,建議改寫為表JOIN。