本文為您介紹使用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技術支持釘釘群,聯系釘群管理員定位解決。
在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