python的udf編寫例子


轉載:https://blog.csdn.net/knidly/article/details/80265616

簡介

Hive為我們提供了眾多的內置函數,但是在實際的運用過程中仍然不能滿足我們所有的需求.hive是用java開發的,本身提供了使用java去開發UDF的方式.而這里我們采用python的方式去實現UDF函數.

DEMO實現

我們這里用python自定義函數,去實現一個方法,利用身份證號去判斷性別(18位身份證的倒數第二位偶數為女,奇數為男.15位身份證的倒數第一位偶數為女,奇數為男.).其實這個需求可以使用hive自帶的function去進行解決.我們接下來使用2種方式去實現這個需求.

數據准備

我們在hive上創建一個external表(名字person表),執行如下代碼:

create external table person(
name string,
idcard string)
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY '\t'
STORED as TEXTFILE;

該表兩個字段,一個為name,另一個為idcard 

數據格式如下:

neil    411326199402110030
pony    41132519950911004x
jcak    12312423454556561
tony    412345671234908

field分隔符使用\t 

我們將數據放入hive的warehouse中:

hdfs dfs -put person.txt /user/hive/warehouse/test_neil.db/person

 

執行select,我們發現數據已經進入到hive了.

使用Hive Function去實現

我們可以執行一下的hql去實現

select idcard,
case when length(idcard) = 18 then
             case when substring(idcard,-2,1) % 2 = 1 then '' 
             when substring(idcard,-2,1) % 2 = 0 then '' 
             else 'unknown' end 
     when length(idcard) = 15 then 
            case when substring(idcard,-1,1) % 2 = 1 then ''
            when substring(idcard,-1,1) % 2 = 0 then ''
            else 'unknown' end
     else '不合法' end 
from person;

 

得到的結果如下(beeline下):

+---------------------+------+--+
|       idcard        | _c1  |
+---------------------+------+--+
| 12312423454556561   | 不合法  |
| 123124234545565     ||
| 411325199308110030  ||
| 41132519950911004x  ||

 

UDF編寫

如下是我們的udf代碼:

# -*- coding: utf-8 -*-
import sys
 
for line in sys.stdin:
    detail = line.strip().split("\t")
    if len(detail) != 2:
        continue
    else:
        name = detail[0]
        idcard = detail[1]
        if len(idcard) == 15:
            if int(idcard[-1]) % 2 == 0:
                print("\t".join([name,idcard,""]))
            else:
                print("\t".join([name,idcard,""]))
        elif len(idcard) == 18:
            if int(idcard[-2]) % 2 == 0:
                print("\t".join([name,idcard,""]))
            else:
                print("\t".join([name,idcard,""]))
        else:
            print("\t".join([name,idcard,"身份信息不合法!"]))

 

這里我們使用python的重定向,將hive控制台的輸出進行split,split默認使用的為\t.然后根據split后的idcard的倒數第二位進行判斷這個人的性別.

 測試

我們在hive中去執行查詢時,報錯的提示不是很詳細.我們可以使用cat指令去測試python腳本的執行效果. 
我們在終端中執行如下指令:

cat person.txt|python person.py

 

輸入結果如下:

neil    411325199308110030  男
pony    41132519950911004x  女
jack    12312423454556561   身份信息不合法!
tony    123124234545565 男

 

說明我們的解析是成功的.

使用

我們在hive中使用python定義的UDF函數要借助transform函數去執行. 
transform函數的語法如下:

SELECT TRANSFORM (<columns>)
USING 'python <python_script>'
AS (<columns>)
FROM <table>;

 

transfrom和as的columns的個數不必一致. 

我們首先需要將我們的person.py加載入

我們在hive中去執行如下代碼:

add file /xxx/person.py

xxx為本地文件的路徑. 
然后使用transform函數執行:

select transform(name,idcard) USING 'python person.py' AS (name,idcard,gender) from person;

java版本也需要打成jar包,使用add方式添加到hive中

add jar jar_path;

並且要創建函數:

create function fun_name as 'java class name' USING jar 'hdfs_jar_path';
// 上方為官方文檔案例,下面的是我自己寫的,屬於臨時函數,重啟hive后失效
create function fun_name as 'java class name';

 

查詢:

select fun_name(字段...) from table_name;

我們同樣可以得到如下的結果:

neil    411325199308110030  男
pony    41132519950911004x  女
jack    12312423454556561   身份信息不合法!
tony    123124234545565

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM