換了新公司,一切也重新開始,接觸到的第一個活就是可能需要將之前python寫的一套數(shù)據(jù)傳輸?shù)拇a,改用Java實現(xiàn),提高開發(fā)效率;
整個業(yè)務(wù)分為兩部分:
- 抽取接口數(shù)據(jù),pickle序列化后打包上傳到云服務(wù)器;
- 從云服務(wù)器下載,解析入庫;
我主要做的是先將解析入庫這部分Java化,其中一個很大的問題就是解析pickle序列化后的數(shù)據(jù),這個問題折磨我了2天。。
主要是好像這種問題網(wǎng)上很少解決方案,也不知道是不是我這操作太奇葩了。。度娘就別想了,只能借助梯子了??催^網(wǎng)上的示例都沒有能正常跑的,或多或少都有些問題,不過也讓我了解到了目前的解決方案,也主要分為兩種:
借助Jython來做,引入jar包后,可以在Java里使用python的代碼,當然這應(yīng)該是對應(yīng)的Java實現(xiàn)吧,但是感覺有點重,jar包有30多M
-
使用pyrolite包,這個包主要是用于與python通信,進行遠程調(diào)用python的方法;
因為我們數(shù)據(jù)打包上傳跟下載解析是分開部署的, 如果在解析那塊還去單獨部署個python用來解析數(shù)據(jù),再用Java去遠程調(diào)用去獲取返回值,這就有點多此一舉了。。所以我們這邊使用的就是通過引入Jython來實現(xiàn)了,到時候數(shù)據(jù)打包如果也改成Java實現(xiàn)的話,那就再改造了。
先說說遇到的幾個坑吧:
init: Bootstrapping class not in BootstrapTypesSingleton.getClassToType()[class=class org.python.core.PyBaseString]
解決這個問題花的時間最久,不解決的話使用pystring的時候會報空指針錯誤;之前從網(wǎng)上看到過類似的,需要在使用前先執(zhí)行.gcMonitorGlobal方法,但是由于個人粗心。跑去調(diào)用pystring.gcMonitorGlobal,所以并沒有卵用,最后仔細看錯誤發(fā)現(xiàn)是PyBaseString的問題,而PyString又是繼承PyBaseString的,后來在代碼中加入靜態(tài)塊解決該問題;

ValueError: insecure string pickle
不安全的值,原因是也是格式問題,python序列化后的格式是這樣的

然后讀取時,在每行尾部需要加上"\n"換行才可以

至此遇到的大問題都已經(jīng)解決,其他問題的話就比較常見了(比如格式轉(zhuǎn)換異常這種),主要是也沒有搜到什么完整的解決方案,也是自己東拼西湊才搞定的,也是不容易,還是因為對python也不太了解吧,遇到?jīng)]見過的報錯有點懵,而且有時候報的錯也不一定是真實的錯。例如ValueError這個錯,最開始報的是空指針,通過調(diào)試代碼看,是Jython里的異常類toString的時候空指針,導致無法發(fā)現(xiàn)真實的錯誤,只能一步步調(diào)試,才發(fā)現(xiàn)。。有點坑
因為確實搜索過沒有發(fā)現(xiàn)什么完整的解決方案或代碼示例,所以整理出來希望能幫到大家!
參考網(wǎng)站:
http://bugs.jython.org/issue2492
https://github.com/irmen/Pyrolite
https://nikoskatsanos.com/blog/2017/01/08/python-unpickling-in-java/
http://www.roman10.net/2012/10/10/loading-python-pickle-files-from-java/