本文為您介紹使用PyODPS時的常見問題。
問題類別 | 常見問題 |
安裝PyODPS | |
匯入模組 | |
使用PyODPS |
安裝PyODPS時,提示Warning: XXX not installed,如何解決?
產生此問題的原因為組件缺失,請根據報錯資訊中提示的XXX資訊,明確缺失的組件名稱,使用pip
命令安裝此組件。
安裝PyODPS時,提示Project Not Found,如何解決?
產生此問題的原因為:
Endpoint配置錯誤,需要修改為目標Project的Endpoint。更多Endpoint資訊,請參見Endpoint。
MaxCompute入口對象參數位置填寫錯誤。請檢查此項確保其填寫正確。更多MaxCompute入口對象參數資訊,請參見從DataWorks遷移到本地環境。
安裝PyODPS時,報錯Syntax Error,如何解決?
由於Python版本過低導致報錯。不支援Python2.5及以下版本,建議使用PyODPS支援的主流版本,例如Python2.7.6+、Python3.3+以及Python2.6。
在Mac上安裝PyODPS時,報錯Permission Denied,如何解決?
您可以使用sudo pip install pyodps
命令安裝PyODPS。
在Mac上安裝PyODPS時,報錯Operation Not Permitted,如何解決?
此報錯是由系統完整性保護導致。您需要重啟裝置,並在重啟中按⌘+R鍵,此後在終端中運行如下命令可以解決此問題。
csrutil disable
reboot
更多資訊,請參見Operation Not Permitted when on root - El Capitan (rootless disabled)。
執行from odps import ODPS時,報錯No Module Named ODPS,如何解決?
此報錯說明無法載入ODPS Package。無法載入的原因有如下幾種:
原因一:安裝了多個Python版本。
解決措施:Search Path(通常是目前的目錄)中包含
odps.py
或init.py
檔案且名為odps的檔案夾。解決方案如下:如果是檔案夾重名,請修改檔案夾名稱。
如果是曾經安裝過一個名為odps的Python包,請使用
sudo pip uninstall odps
進行刪除。
原因二:同時安裝了Python2和Python3版本。
解決措施:確保裝置只安裝了Python2或Python3版本。
原因三:當前使用的Python下並未安裝PyODPS。
解決措施:安裝PyODPS,安裝方法請參見安裝PyODPS。
執行from odps import ODPS時,報錯Cannot Import Name ODPS,如何解決?
請檢查當前工作路徑下是否存在名為odps.py的檔案。若存在,請改名後再執行匯入操作。
執行from odps import ODPS時,報錯Cannot Import Module odps,如何解決?
此報錯通常是由於PyODPS遇到了依賴問題。您可以單擊申請連結添加PyODPS支援人員DingTalk群,聯絡釘群管理員定位解決。
在IPython或Jupyter下使用PyODPS時,報錯ImportError,如何解決?
在代碼頭部增加from odps import errors
。
如果增加from odps import errors
也報錯則是缺少Ipython組件,執行sudo pip install -U jupyter
解決此問題。
o.gettable('table_name').size中size欄位的含義是什嗎?
SIZE欄位表示表的實體儲存體大小。
如何設定Tunnel Endpoint?
您可以通過options.tunnel.endpoint
設定,請參見aliyun-odps-python-sdk。
PyODPS如何使用包含CPython的第三方包?
建議您打包成WHEEL格式後使用,請參見如何製作可以在MaxCompute上使用的crcmod。
PyODPS中的DataFrame最多可以處理多少資料,對錶的大小有限制嗎?
PyODPS對錶的大小沒有限制。本地Pandas建立DataFrame的大小受限於本地記憶體的大小。
在DataFrame中如何使用max_pt?
使用odps.df.func
模組來調用MaxCompute內建函數。
from odps.df import func
df = o.get_table('your_table').to_df()
df[df.ds == func.max_pt('your_project.your_table')] # ds是分區欄位。
使用PyODPS向表寫入資料的兩種方式open_writer()和write_table()有什麼區別?
每次調用write_table()
,MaxCompute都會在服務端產生一個檔案。這一操作需要較大的時間開銷,同時過多的檔案會降低後續的查詢效率,還可能造成服務端記憶體不足。因此,建議在使用write_table()
方法時,一次性寫入多組資料或者傳入一個Generator對象。使用write_table()
方法樣本請參見寫入表資料。
open_writer()
預設寫入到Block中。
為什麼DataWorks PyODPS節點上查出的資料量要少於本地啟動並執行結果?
DataWorks上預設未開啟Instance Tunnel,即instance.open_reader
預設使用Result介面,最多可以擷取一萬條記錄。
開啟Instance Tunnel後,您可以通過reader.count
擷取記錄數。如果您需要迭代擷取全部資料,則需要通過設定options.tunnel.limit_instance_tunnel = False
關閉Limit限制。
DataFrame如何獲得Count實際數字?
安裝PyODPS後,在Python環境下執行如下命令建立MaxCompute表來初始化DataFrame。
iris = DataFrame(o.get_table('pyodps_iris'))
在DataFrame上執行Count擷取DataFrame的總行數。
iris.count()
由於DataFrame上的操作並不會立即執行,只有當使用者顯式調用Execute方法或者立即執行的方法時,才會真正執行。此時為了防止Count方法順延強制,可輸入如下命令。
df.count().execute()
使用PyODPS時,報錯sourceIP is not in the white list,如何解決?
PyODPS訪問的MaxCompute專案存在白名單保護,請聯絡專案所有者將裝置添加至IP白名單。更多IP白名單資訊,請參見管理IP白名單。
使用from odps import options options.sql.settings設定MaxCompute運行環境不成功,如何解決?
問題現象
使用PyODPS運行SQL,在申請MaxCompute執行個體前,通過如下代碼設定MaxCompute運行環境。
from odps import options options.sql.settings = {'odps.sql.mapper.split.size': 32}
運行任務後只啟動了6個Mapper,設定未生效。 在用戶端執行
set odps.stage.mapper.split.size=32
,一分鐘運行完畢。產生原因
用戶端和PyODPS裡設定的參數不一致。用戶端的參數是
odps.stage.mapper.split.size
,而PyODPS裡的參數是odps.sql.mapper.split.size
。解決措施
修改參數為
odps.stage.mapper.split.size
。
調用DataFrame的head方法時,報錯IndexError:listindexoutofrange,是什麼原因?
由於list[index]
沒有元素或list[index]
超出範圍。
上傳Pandas DataFrame至MaxCompute時,報錯ODPSError,如何解決?
問題現象
上傳Pandas DataFrame至MaxCompute時,返回報錯如下。
ODPSError: ODPS entrance should be provided.
產生原因
報錯原因為沒有找到全域的MaxCompute對象入口。
解決措施
使用Room機制
%enter
時,會配置全域入口。對MaxCompute對象入口調用
to_global
方法。使用參數
DataFrame(pd_df).persist('your_table', odps=odps)
。
通過DataFrame寫表時,報錯lifecycle is not specified in mandatory mode,如何解決?
問題現象
通過DataFrame寫表時,返回報錯如下。
table lifecycle is not specified in mandatory mode
產生原因
未給表設定生命週期。
解決措施
Project要求對每張表設定生命週期,因此需要在每次執行時設定如下資訊即可。
from odps import options options.lifecycle = 7 # 此處設定lifecycle的值。lifecycle取值為整數,單位為天。
使用PyODPS寫資料時,提示Perhaps the datastream from server is crushed,如何解決?
該報錯是由髒資料導致,請您檢查資料列數是否和目標表一致。
使用PyODPS讀資料時,報錯Project is protected,如何解決?
Project上的安全性原則禁止讀取表中的資料,如果想使用全部資料,可以使用以下方法:
聯絡Project Owner增加例外規則。
使用DataWorks或其他脫敏工具先對資料進行脫敏,匯出到非保護Project,再進行讀取。
如果只想查看部分資料,可使用如下方法:
改用
o.execute_sql('select * from <table_name>').open_reader()
。改用
DataFrame,o.get_table('<table_name>').to_df()
。
PyODPS指令碼任務不定時出現串連失敗,報錯ConnectionError: timed out try catch exception,如何解決?
產生此報錯的可能原因如下:
建立連線逾時。PyODPS預設的逾時時間是5s,解決方案如下:
您可以在代碼頭部加上如下代碼,增加逾時時間隔。
workaround from odps import options options.connect_timeout=30
捕獲異常,進行重試。
由於沙箱限制,會造成部分機器禁止網路訪問。建議您使用獨享調度資源群組執行任務,解決此問題。
使用PyODPS運行get_sql_task_cost函數時,報錯is not defined,如何解決?
問題現象
使用PyODPS運行get_sql_task_cost函數時,返回報錯如下。
NameError: name 'get_task_cost' is not defined.
解決措施
函數名稱有誤。
解決措施
使用execute_sql_cost替代get_sql_task_cost。
使用PyODPS列印日誌時,中文自動轉換為編碼顯示,如何顯示成原始中文?
您可以使用類似print ("我叫 %s" % ('abc'))
的輸入方式解決。目前僅Python 2涉及此類問題。
設定options.tunnel.use_instance_tunnel = False,為什麼欄位在MaxCompute中定義為DATETIME類型,使用SELECT語句得到的資料為STRING類型?
在調用Open_Reader時,PyODPS會預設調用舊的Result介面。此時從服務端得到的資料是CSV格式的,所以DATETIME都是STRING類型。
開啟Instance Tunnel,即設定options.tunnel.use_instance_tunnel = True
,PyODPS會預設調用Instance Tunnel,即可解決此問題。
如何利用Python語言特性來實現豐富的功能?
編寫Python函數。
計算兩點之間的距離有多種計算方法,例如歐氏距離、曼哈頓距離等,您可以定義一系列函數,在計算時根據具體情況調用相應的函數即可。
def euclidean_distance(from_x, from_y, to_x, to_y): return ((from_x - to_x) ** 2 + (from_y - to_y) ** 2).sqrt() def manhattan_distance(center_x, center_y, x, y): return (from_x - to_x).abs() + (from_y - to_y).abs()
調用如下。
In [42]: df from_x from_y to_x to_y 0 0.393094 0.427736 0.463035 0.105007 1 0.629571 0.364047 0.972390 0.081533 2 0.460626 0.530383 0.443177 0.706774 3 0.647776 0.192169 0.244621 0.447979 4 0.846044 0.153819 0.873813 0.257627 5 0.702269 0.363977 0.440960 0.639756 6 0.596976 0.978124 0.669283 0.936233 7 0.376831 0.461660 0.707208 0.216863 8 0.632239 0.519418 0.881574 0.972641 9 0.071466 0.294414 0.012949 0.368514 In [43]: euclidean_distance(df.from_x, df.from_y, df.to_x, df.to_y).rename('distance') distance 0 0.330221 1 0.444229 2 0.177253 3 0.477465 4 0.107458 5 0.379916 6 0.083565 7 0.411187 8 0.517280 9 0.094420 In [44]: manhattan_distance(df.from_x, df.from_y, df.to_x, df.to_y).rename('distance') distance 0 0.392670 1 0.625334 2 0.193841 3 0.658966 4 0.131577 5 0.537088 6 0.114198 7 0.575175 8 0.702558 9 0.132617
利用Python語言的條件和迴圈語句。
如果使用者要計算的表儲存在資料庫,需要根據配置來對錶的欄位進行處理,然後對所有表進行UNION或者JOIN操作。這時如果用SQL實現是相當複雜的,但是用DataFrame處理則會非常簡單。
例如,您有30張表需要合成一張表,此時如果使用SQL,則需要對30張表執行UNION ALL操作。如果使用PyODPS,如下代碼就可以完成。
table_names = ['table1', ..., 'tableN'] dfs = [o.get_table(tn).to_df() for tn in table_names] reduce(lambda x, y: x.union(y), dfs) ## reduce語句等價於如下代碼。 df = dfs[0] for other_df in dfs[1:]: df = df.union(other_df)
如何使用Pandas計算後端進行本地Debug?
您可以通過如下兩種方式來進行本地Debug。這兩種方式除了初始化方法不同,後續代碼完全一致:
通過Pandas DataFrame建立的PyODPS DataFrame可以使用Pandas執行本地計算。
使用MaxCompute表建立的DataFrame可以在MaxCompute上執行。
範例程式碼如下。
df = o.get_table('movielens_ratings').to_df()
DEBUG = True
if DEBUG:
df = df[:100].to_pandas(wrap=True)
當所有後續代碼都編寫完成,本地的測試速度非常快。當測試結束後,您可以把Debug值改為False,這樣後續就能在MaxCompute上執行全量的計算。
推薦您使用MaxCompute Studio來執行本地PyODPS程式調試。
如何避免嵌套迴圈執行慢的情況?
建議您通過Dict資料結構記錄下迴圈的執行結果,最後在迴圈外統一匯入到Dataframe對象中。如果您將Dataframe對象代碼df=XXX
放置在外層迴圈中,會導致每次迴圈計算都產生一個Dataframe對象,從而降低嵌套迴圈整體的執行速度。
如何避免將資料下載到本地?
什麼情況下可以下載PyODPS資料到本地處理?
在如下兩種情況下,可以下載PyODPS資料到本地:
資料量很小的情況下進行本機資料處理。
如果需要對單行資料應用一個Python函數,或者執行一行變多行的操作,這時使用PyODPS DataFrame就可以輕鬆完成,並且可以完全發揮MaxCompute的並行計算能力。
例如有一份JSON串資料,需要把JSON串按Key-Value對展開成一行,代碼如下所示。
In [12]: df json 0 {"a": 1, "b": 2} 1 {"c": 4, "b": 3} In [14]: from odps.df import output In [16]: @output(['k', 'v'], ['string', 'int']) ...: def h(row): ...: import json ...: for k, v in json.loads(row.json).items(): ...: yield k, v ...: In [21]: df.apply(h, axis=1) k v 0 a 1 1 b 2 2 c 4 3 b 3
通過open_reader最多隻能取到1萬條記錄,如何擷取多於1萬條的記錄?
使用create table as select ...
將SQL的結果儲存成表,再使用table.open_reader
讀取。
為什麼盡量使用內建運算元,而不是自訂函數?
計算過程中使用自訂函數比使用內建運算元速度慢很多,因此建議使用內建運算元。
對於百萬行的資料,當一行應用了自訂函數後,執行時間從7秒延長到了27秒。如果有更大的資料集、更複雜的操作,時間的差距可能會更大。
為什麼通過DataFrame().schema.partitions獲得分區表的分區值為空白?
這是因為DataFrame不區分分區欄位和普通欄位,所以擷取分區表的分區欄位作為普通欄位處理。您可以通過如下方式過濾掉分區欄位。
df = o.get_table().to_df()
df[df.ds == '']
建議您參照表來設定分區或讀取分區資訊。
如何使用PyODPS DataFrame執行笛卡爾積?
如何使用PyODPS實現結巴中文分詞?
請參見PyODPS節點實現結巴中文分詞。
如何使用PyODPS下載全量資料?
PyODPS預設不限制從Instance讀取的資料規模。但是對於受保護的MaxCompute專案,通過Tunnel下載資料將受限。此時,如果未設定options.tunnel.limit_instance_tunnel
,則資料量限制會被自動開啟,可下載的資料條數受到MaxCompute配置限制,通常該限制為10000條。如果您需要迭代擷取全部資料,則需要關閉limit
限制。您可以通過下列語句在全域範圍內開啟Instance Tunnel
並關閉limit
限制。
options.tunnel.use_instance_tunnel = True
options.tunnel.limit_instance_tunnel = False # 關閉limit限制,讀取全部資料。
with instance.open_reader() as reader:
# 通過Instance Tunnel可讀取全部資料。
使用PyODPS統計表中某個欄位的空值率時,是用execute_sql還是DataFrame?
DataFrame彙總效能更高一些,推薦使用DataFrame來執行彙總操作。
PyODPS資料類型如何設定?
如果您使用PyODPS,可以通過下列方法開啟新資料類型開關:
如果通過
execute_sql
方式開啟新資料類型,可以執行o.execute_sql('set odps.sql.type.system.odps2=true;query_sql', hints={"odps.sql.submit.mode" : "script"})
。如果通過Dataframe開啟新資料類型,例如persist、execute、to_pandas等方法,可通過hints參數設定。圖示設定方法僅針對單個作業生效。
from odps.df import DataFrame users - DataFrame(o.get_table('odps2_test')) users.persist('copy_test',hints={'odps.sql.type.system.odps2':'true'})
如果通過Dataframe調用,且需要全域生效,需要使用Option參數
options.sql.use_odps2_extension = True
。
使用PyODPS時遇到ValueError,如何解決?
您可以通過以下兩種方式進行解決:
升級SDK版本至V0.8.4或以上版本。
SQL中添加如下語句:
fromodps.typesimportDecimal Decimal._max_precision=38