MaxCompute menjalankan fungsi user-defined table-valued (UDTF) Python 2 menggunakan Python 2.7. UDTF menerima satu baris input dan mengembalikan nol atau lebih baris output, sehingga cocok untuk operasi seperti pemisahan atau perluasan data.
Untuk membuat dan menggunakan UDTF Python 2:
Tulis kelas Python yang memperluas
BaseUDTFdan mengimplementasikan metode yang diperlukan.Daftarkan kelas tersebut sebagai UDTF di MaxCompute, lalu panggil dalam SQL MaxCompute.
Struktur kode UDTF
UDTF Python 2 terdiri dari hingga lima komponen.
| Komponen | Wajib | Deskripsi |
|---|---|---|
| Deklarasi encoding | Tidak | Mendeklarasikan encoding file. Gunakan #coding:utf-8 atau # -*- coding: utf-8 -*-. Tambahkan ini jika kode berisi karakter Tionghoa—tanpa deklarasi tersebut, MaxCompute akan mengembalikan error pada waktu proses. |
| Impor modul | Ya | Harus menyertakan from odps.udf import annotate dan from odps.udf import BaseUDTF. Tambahkan from odps.distcache import get_cache_file atau from odps.distcache import get_cache_table jika UDTF mereferensikan resource file atau tabel. |
| Signature fungsi | Tidak | Menganotasi UDTF dengan @annotate(<signature>) untuk mendeklarasikan tipe data input dan output. Tanpa signature, MaxCompute menerima semua tipe input tetapi memperlakukan semua nilai output sebagai STRING. |
| Kelas turunan | Ya | Kelas Python yang memperluas BaseUDTF. Kelas ini berisi seluruh logika UDTF. |
| Metode kelas | Ya | Implementasikan minimal metode process. Lihat tabel metode di bawah ini. |
Metode
| Metode | Wajib | Deskripsi |
|---|---|---|
BaseUDTF.init() | Tidak | Menginisialisasi state sebelum record pertama diproses. Jika Anda meng-override init, panggil super(BaseUDTF, self).init() di awal. Gunakan metode ini untuk menyiapkan state yang perlu dipertahankan UDTF di seluruh record. |
BaseUDTF.process([args, ...]) | Ya | Dipanggil sekali untuk setiap baris input. Argumen sesuai dengan parameter input UDTF sebagaimana dideklarasikan dalam SQL. |
BaseUDTF.forward([args, ...]) | Ya (dipanggil di dalam process) | Menghasilkan satu baris output setiap kali dipanggil. Panggil sekali untuk setiap baris yang ingin Anda kembalikan. Jika tidak ada signature fungsi yang didefinisikan, konversi semua argumen ke STRING sebelum memanggil forward. |
BaseUDTF.close() | Tidak | Dipanggil sekali sebelum record terakhir diproses. Gunakan metode ini untuk melepas resource atau mengosongkan output. |
Contoh
UDTF berikut memisahkan string yang dipisahkan koma dan menghasilkan setiap nilai sebagai baris terpisah.
#coding:utf-8
from odps.udf import annotate
from odps.udf import BaseUDTF
@annotate('string -> string')
class Explode(BaseUDTF):
def process(self, arg):
props = arg.split(',')
for p in props:
self.forward(p)Signature fungsi dan tipe data
Format signature
@annotate('arg_type_list -> type_list')arg_type_list: daftar tipe parameter input yang dipisahkan koma. Gunakan*untuk menerima jumlah argumen apa pun, atau biarkan kosong jika tidak ada argumen.type_list: daftar tipe nilai kembali yang dipisahkan koma. UDTF dapat mengembalikan beberapa kolom.
Tabel berikut menunjukkan contoh signature yang valid.
| Signature | Tipe input | Tipe kembali |
|---|---|---|
@annotate('bigint,boolean->string,datetime') | BIGINT, BOOLEAN | STRING, DATETIME |
@annotate('*->string,datetime') | Jumlah argumen apa pun | STRING, DATETIME |
@annotate('->double,bigint,string') | Tidak ada | DOUBLE, BIGINT, STRING |
@annotate("array<string>,struct<a1:bigint,b1:string>,string->map<string,bigint>,struct<b1:bigint>") | ARRAY, STRUCT, STRING | MAP, STRUCT |
Selama penguraian semantik, MaxCompute memeriksa apakah tipe data argumen aktual sesuai dengan signature. Ketidaksesuaian akan menghasilkan error.
Tipe data yang tersedia bergantung pada edisi tipe data proyek MaxCompute Anda. Untuk informasi selengkapnya, lihat Edisi tipe data.
Pemetaan tipe data
Tulis kode UDTF menggunakan tipe Python yang sesuai dengan tipe SQL MaxCompute.
| Tipe SQL MaxCompute | Tipe Python 2 |
|---|---|
| BIGINT | int |
| STRING | str |
| DOUBLE | float |
| BOOLEAN | bool |
| DATETIME | int (milidetik sejak 1 Januari 1970, 00:00:00 UTC) |
| FLOAT | float |
| CHAR | str |
| VARCHAR | str |
| BINARY | bytearray |
| DATE | int |
| DECIMAL | decimal.Decimal |
| ARRAY | list |
| MAP | dict |
| STRUCT | collections.namedtuple |
Catatan tambahan mengenai penanganan tipe:
NULL dalam SQL MaxCompute dipetakan ke
Nonedalam Python.odps.udf.int(value, silent=True)mengembalikanNonealih-alih memunculkan error ketika nilai tidak dapat dikonversi ke int.
Referensi resource file dan tabel
Gunakan modul odps.distcache untuk memuat resource file atau tabel ke dalam UDTF Anda.
get_cache_file(resource_name): mengembalikan objek mirip file untuk resource file bernama tersebut. Panggilclose()pada objek tersebut setelah selesai. Deklarasikan resource file saat mendaftarkan UDTF—jika tidak, pemanggilan akan gagal pada waktu proses.get_cache_table(resource_name): mengembalikan generator atas resource tabel bernama tersebut. Setiap iterasi menghasilkan catatan sebagai daftar (tipe ARRAY).
Contoh berikut memuat file JSON dan resource tabel, lalu menggunakannya untuk mencari ID iklan berdasarkan ID halaman.
# -*- coding: utf-8 -*-
from odps.udf import annotate
from odps.udf import BaseUDTF
from odps.distcache import get_cache_file
from odps.distcache import get_cache_table
@annotate('string -> string, bigint')
class UDTFExample(BaseUDTF):
def __init__(self):
import json
# Muat resource file JSON ke dalam dict
cache_file = get_cache_file('test_json.txt')
self.my_dict = json.load(cache_file)
cache_file.close()
# Gabungkan catatan dari resource tabel
records = list(get_cache_table('table_resource1'))
for record in records:
self.my_dict[record[0]] = [record[1]]
def process(self, pageid):
# Hasilkan satu baris per ID iklan yang terkait dengan halaman
for adid in self.my_dict[pageid]:
self.forward(pageid, adid)Panggil UDTF dalam SQL MaxCompute
Setelah menyelesaikan proses pengembangan, panggil UDTF dari SQL MaxCompute:
Dalam satu proyek: Panggil UDTF dengan cara yang sama seperti memanggil fungsi bawaan.
Antar proyek: Untuk menggunakan UDTF dari proyek B di proyek A, tambahkan awalan nama proyek pada nama fungsi:
SELECT B:udf_in_other_project(arg0, arg1) AS res FROM table_t;Untuk informasi selengkapnya, lihat Akses resource antar proyek berbasis paket.
Batasan
MaxCompute menjalankan kode UDTF Python 2 dalam lingkungan sandbox. Operasi berikut tidak diizinkan:
Membaca dari atau menulis ke file lokal
Menjalankan subprocess
Menjalankan thread
Membuka koneksi socket
Memanggil UDF Python 2 dari sistem lain
Unggah hanya kode yang menggunakan pustaka standar Python. Modul atau modul ekstensi C yang bergantung pada operasi terbatas di atas tidak tersedia.
Modul ekstensi C yang tersedia
Modul ekstensi C berikut tersedia di lingkungan sandbox:
array, audioop, binascii, bisect, cmath, _codecs_cn, _codecs_hk, _codecs_iso2022, _codecs_jp, _codecs_kr, _codecs_tw, _collections, cStringIO, datetime, _functools, future_builtins, _heapq, _hashlib, itertools, _json, _locale, _lsprof, math, _md5, _multibytecodec, operator, _random, _sha256, _sha512, _sha, _struct, strop, time, unicodedata, _weakref, cPickle
Semua modul yang diimplementasikan murni dalam Python dan tidak bergantung pada modul ekstensi juga tersedia.
Batas ukuran output
Penulisan ke sys.stdout atau sys.stderr dibatasi hingga 20 KB. Karakter yang melebihi batas ini akan diam-diam diabaikan.
Pustaka pihak ketiga
Pustaka pihak ketiga, seperti NumPy, telah dipra-instal di lingkungan Python 2 MaxCompute. Akses data lokal dan sebagian besar API I/O jaringan dinonaktifkan untuk pustaka pihak ketiga—hanya I/O jaringan terbatas yang tersedia.