Yayasan Perangkat Lunak Python telah mengumumkan Akhir Masa Pakai (EOL) untuk Python 2. Oleh karena itu, MaxCompute mendukung Python 3 dan menggunakan CPython 3.7.3. Topik ini menjelaskan cara menulis fungsi agregat yang didefinisikan pengguna (UDAF) dalam Python 3.
Struktur kode UDAF
- Impor modul: wajib.
Kode UDAF harus mencakup setidaknya
from odps.udf import annotatedanfrom odps.udf import BaseUDAF.from odps.udf import annotatedigunakan untuk mengimpor modul tanda tangan fungsi, sehingga MaxCompute dapat mengidentifikasi tanda tangan fungsi yang didefinisikan dalam kode.from odps.udf import BaseUDAFadalah kelas dasar untuk UDAF Python. Anda harus menggunakan kelas ini untuk mengimplementasikan metode sepertiiterate,merge, atauterminatedi kelas turunan.Jika Anda ingin merujuk file atau sumber daya tabel dalam kode UDAF, kode tersebut harus mencakup
from odps.distcache import get_cache_fileataufrom odps.distcache import get_cache_table. - Tanda tangan fungsi: wajib.
Tanda tangan fungsi berada dalam format
@annotate(<signature>). Parametersignaturedigunakan untuk mendefinisikan tipe data parameter input dan nilai balikan dari UDF. Untuk informasi lebih lanjut tentang tanda tangan fungsi, lihat Tanda Tangan Fungsi dan Tipe Data. - Kelas Python kustom (kelas turunan): wajib.
Kelas Java kustom adalah unit organisasi dalam kode UDAF. Kelas ini mendefinisikan variabel dan metode yang digunakan untuk memenuhi kebutuhan bisnis Anda. Dalam kode UDF, Anda dapat mereferensikan pustaka pihak ketiga yang diinstal di MaxCompute atau mereferensikan file atau tabel. Untuk informasi lebih lanjut, lihat Pustaka pihak ketiga atau Sumber referensi.
- Metode untuk mengimplementasikan kelas Python: wajib.
Tabel berikut menjelaskan empat metode yang dapat digunakan untuk mengimplementasikan kelas Python. Anda dapat memilih metode berdasarkan kebutuhan bisnis Anda.
Metode Deskripsi BaseUDAF.new_buffer()Mengembalikan buffer nilai antara dari UDAF. bufferharus berupa objek yang dapat dimarshalkan, seperti LIST atau DICT, dan ukuranbuffertidak boleh bertambah dengan jumlah data. Dalam kasus ekstrem, ukuranbuffertidak boleh melebihi 2 MB setelah operasi marshaling.BaseUDAF.iterate(buffer[, args, ...])Menggabungkan argske dalam nilai antarabuffer.BaseUDAF.merge(buffer, pbuffer)Menyimpan hasil penggabungan dari pbufferdan nilai antarabufferdi dalambuffer.BaseUDAF.terminate(buffer)Mengonversi buffermenjadi nilai dari tipe data dasar dalam SQL MaxCompute.
# Impor modul tanda tangan fungsi dan kelas dasar.
from odps.udf import annotate
from odps.udf import BaseUDAF
# Tanda tangan fungsi.
@annotate('double->double')
# Kelas Python kustom.
class Average(BaseUDAF):
# Metode yang digunakan untuk mengimplementasikan kelas Python kustom.
def new_buffer(self):
return [0, 0]
def iterate(self, buffer, number):
if number is not None:
buffer[0] += number
buffer[1] += 1
def merge(self, buffer, pbuffer):
buffer[0] += pbuffer[0]
buffer[1] += pbuffer[1]
def terminate(self, buffer):
if buffer[1] == 0:
return 0.0
return buffer[0] / buffer[1]Peringatan
Python 3 tidak kompatibel dengan Python 2. Oleh karena itu, Anda tidak dapat menggunakan kode Python 2 dan Python 3 dalam satu pernyataan SQL pada saat yang bersamaan.
Yayasan Perangkat Lunak Python mengumumkan akhir masa pakai (EOL) untuk Python 2 pada awal 2020. Oleh karena itu, kami merekomendasikan agar Anda memindahkan UDF Python 2. Untuk proyek MaxCompute yang sudah ada, kami merekomendasikan agar Anda memindahkan UDF Python 2. Untuk proyek baru, kami merekomendasikan agar Anda menggunakan Python 3 untuk menulis semua UDF Python.
Pemindahan Python 2 UDAF
- Proyek baru: Jika proyek Anda adalah proyek MaxCompute baru atau jika ini pertama kalinya Anda menggunakan Python untuk menulis UDAF untuk proyek MaxCompute, kami merekomendasikan agar Anda menggunakan Python 3 untuk menulis semua UDAF Python.
- Proyek yang sudah ada: Jika proyek Anda adalah proyek yang sudah ada untuk mana sejumlah besar UDAF Python 2 telah dibuat, berhati-hatilah saat Anda mengaktifkan Python 3. Jika Anda berencana untuk secara bertahap mengganti UDAF Python 2 dengan UDAF Python 3, gunakan salah satu metode berikut:
- Gunakan Python 3 untuk menulis UDAF baru dan aktifkan Python 3 untuk pekerjaan baru di tingkat sesi. Untuk informasi lebih lanjut tentang cara mengaktifkan Python 3, lihat Aktifkan Python 3.
- Tulis ulang UDAF Python 2 agar kompatibel dengan Python 2 dan Python 3. Untuk informasi lebih lanjut tentang cara menulis ulang UDAF Python 2, lihat Memindahkan Kode Python 2 ke Python 3. Catatan Jika Anda ingin menulis UDAF publik yang dapat dibagikan di antara beberapa proyek, kami merekomendasikan agar UDAF tersebut kompatibel dengan Python 2 dan Python 3.
Pustaka pihak ketiga
Pustaka pihak ketiga NumPy tidak diinstal di lingkungan Python 3 MaxCompute. Untuk menggunakan UDAF NumPy, Anda harus mengunggah paket wheel NumPy secara manual. Jika Anda mengunduh paket wheel NumPy dari Python Package Index (PyPI) atau memperoleh paket ini dari gambar, nama paket tersebut adalah dalam format berikut numpy-<Version>-cp37-cp37m-manylinux1_x86_64.whl. Untuk informasi lebih lanjut tentang cara mengunggah paket, lihat Operasi Sumber Daya atau Contoh: Merujuk Pustaka Pihak Ketiga dalam UDF Python.
Tanda tangan fungsi dan tipe data
@annotate(<signature>)signature adalah string yang menentukan tipe data parameter input dan nilai balikan. Saat Anda menjalankan UDAF, tipe data parameter input dan nilai balikan UDAF harus konsisten dengan tipe data yang ditentukan dalam tanda tangan fungsi. Konsistensi tipe data diperiksa selama penguraian semantik. Jika tipe data tidak konsisten, kesalahan akan dikembalikan. Format tanda tangan fungsi: 'arg_type_list -> type'arg_type_list: menentukan tipe data parameter input. Jika beberapa parameter input digunakan, tentukan beberapa tipe data dan pisahkan dengan koma (,). Tipe data berikut didukung: BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(presisi,skala), CHAR, VARCHAR, tipe data kompleks (ARRAY, MAP, dan STRUCT), dan tipe data kompleks bersarang.arg_type_listdapat direpresentasikan oleh asterisk (*) atau dibiarkan kosong ('').Jika
arg_type_listdirepresentasikan oleh asterisk (*), jumlah parameter input acak diperbolehkan.Jika
arg_type_listdibiarkan kosong (''), tidak ada parameter input yang digunakan.
Untuk informasi lebih lanjut tentang ekstensi sintaksis anotasi @Resolve, lihat Parameter Dinamis UDAF dan UDTF.
typemenentukan tipe data nilai balikan. Untuk UDAF, hanya satu kolom nilai yang dikembalikan. Tipe data berikut didukung: BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, dan DECIMAL(presisi, skala). Tipe data kompleks, seperti ARRAY, MAP, dan STRUCT, serta tipe data kompleks bersarang juga didukung.
Tabel berikut memberikan contoh tanda tangan fungsi yang valid.
| Tanda tangan fungsi | Deskripsi |
@annotate('bigint,double->string') | Tipe data parameter input adalah BIGINT dan DOUBLE dan tipe data nilai balikan adalah STRING. |
@annotate('*->string') | Jumlah parameter input acak digunakan dan tipe data nilai balikan adalah STRING. |
@annotate('->double') | Tidak ada parameter input yang digunakan dan tipe data nilai balikan adalah DOUBLE. |
@annotate('array<bigint>->struct<x:string, y:int>') | Tipe data parameter input adalah ARRAY<BIGINT> dan tipe data nilai balikan adalah STRUCT<x:STRING, y:INT>. |
Tabel berikut menjelaskan pemetaan antara tipe data yang didukung dalam SQL MaxCompute dan tipe data Python 2. Anda harus menulis UDAF Python berdasarkan pemetaan untuk memastikan konsistensi tipe data. Tabel berikut menjelaskan pemetaan tipe data.
Tipe SQL MaxCompute | Tipe Python 3 |
BIGINT | INT |
STRING | UNICODE |
DOUBLE | FLOAT |
BOOLEAN | BOOL |
DATETIME | DATETIME.DATETIME |
FLOAT | FLOAT |
CHAR | UNICODE |
VARCHAR | UNICODE |
BINARY | BYTES |
DATE | DATETIME.DATE |
DECIMAL | DECIMAL.DECIMAL |
ARRAY | LIST |
MAP | DICT |
STRUCT | COLLECTIONS.NAMEDTUPLE |
Sumber referensi
Anda dapat merujuk file dan tabel dalam kode UDAF Python 2 dengan menggunakan modul odps.distcache.
odps.distcache.get_cache_file(resource_name): mengembalikan konten file tertentu.resource_nameadalah string yang menentukan nama file yang ada di proyek MaxCompute Anda. Jika nama file tidak valid atau file tidak ada, kesalahan akan dikembalikan.Catatan Untuk merujuk file dalam kode UDAF, Anda harus mendeklarasikan file saat membuat UDAF. Jika tidak, kesalahan akan dikembalikan saat Anda memanggil UDAF.- Nilai balikan adalah objek mirip file. Jika objek ini tidak lagi digunakan, Anda harus memanggil metode
closeuntuk melepaskan file.
odps.distcache.get_cache_table(resource_name): mengembalikan konten tabel tertentu.resource_nameadalah string yang menentukan nama tabel yang ada di proyek MaxCompute Anda. Jika nama tabel tidak valid atau tabel tidak ada, kesalahan akan dikembalikan.- Nilai balikan adalah tipe GENERATOR. Pemanggil melintasi tabel untuk mendapatkan konten tabel. Rekaman tipe ARRAY diperoleh setiap kali pemanggil melintasi tabel.
Untuk informasi lebih lanjut, lihat Sumber Referensi (UDF Python 3) dan Sumber Referensi (UDTF Python 3).
Catatan penggunaan
Gunakan UDF dalam proyek MaxCompute: Metodenya serupa dengan penggunaan fungsi bawaan.
Gunakan UDF lintas proyek: Gunakan UDF Proyek B di Proyek A. Pernyataan berikut menunjukkan contoh:
select B:udf_in_other_project(arg0, arg1) as res from table_t;. Untuk informasi lebih lanjut tentang berbagi lintas proyek, lihat Akses Sumber Daya Lintas Proyek Berbasis Paket.
Untuk informasi lebih lanjut tentang cara menggunakan MaxCompute Studio untuk mengembangkan dan memanggil UDAF Python 3, lihat Kembangkan UDF Python.
Parameter dinamis UDAF
Tanda tangan fungsi
- Anda dapat menggunakan asterisk (
*) dalam daftar parameter untuk menunjukkan bahwa parameter input dapat memiliki panjang dan tipe apa pun. Sebagai contoh,@annotate('double,*->string')menunjukkan daftar parameter di mana parameter pertama adalah tipe data DOUBLE dan diikuti oleh parameter dengan panjang dan tipe apa pun. Dalam hal ini, Anda harus menyusun kode untuk menghitung jumlah dan tipe parameter input, dan mengelolanya berdasarkan fungsiprintfdalam bahasa pemrograman C.CatatanAsterisk (*)dalam nilai balikan menunjukkan arti yang berbeda. Asterisk (*)dapat digunakan dalam nilai balikan UDTF untuk menunjukkan bahwa sejumlah nilai tipe data STRING dapat dikembalikan. Jumlah nilai balikan didasarkan pada jumlah alias yang dikonfigurasi saat fungsi dipanggil. Sebagai contoh, metode panggilan@annotate("bigint,string->double,*")adalahUDTF(x, y) as (a, b, c). Dalam contoh ini, aliasa,b, dancdikonfigurasi setelahas. Editor mengidentifikasi bahwaaadalah tipe DOUBLE danbdancadalah tipe STRING. Tipe data nilai balikan di kolom pertama yang dikembalikan dalam anotasi Resolve diberikan. Tiga nilai balikan disediakan dalam contoh ini. Oleh karena itu, metodeforwardyang dipanggil oleh UDTF harusforwardarray dengan tiga elemen. Jika tidak, kesalahan akan dikembalikan.Catatan Namun, kesalahan tidak dikembalikan selama kompilasi. Oleh karena itu, pemanggil UDTF harus mengonfigurasi jumlah alias dalam SQL berdasarkan aturan yang didefinisikan dalam UDTF. Jumlah nilai balikan dari fungsi agregat tetap 1. Oleh karena itu, aturan ini tidak berpengaruh pada UDAF.
Contoh UDAF
from odps.udf import annotate
from odps.udf import BaseUDAF
@annotate('bigint,*->string')
class MultiColSum(BaseUDAF):
def new_buffer(self):
return [0]
def iterate(self, buffer, *args):
for arg in args:
buffer[0] += int(arg)
def merge(self, buffer, pbuffer):
buffer[0] += pbuffer[0]
def terminate(self, buffer):
return str(buffer[0])Jumlah nilai balikan UDAF hanya dapat ditetapkan menjadi satu. Dalam contoh sebelumnya, nilai balikan adalah jumlah nilai dari beberapa parameter input dan jumlah nilai dalam beberapa baris. Contoh pernyataan: -- Hitung jumlah nilai dari beberapa parameter input.
SELECT my_multi_col_sum(a,b,c,d,e) from values (1,"2","3","4","5"), (6,"7","8","9","10") t(a,b,c,d,e);
-- Nilai balikannya adalah 55.