Python Software Foundation, Python 2 desteğini yakında sonlandıracaktır. MaxCompute artık Python 3'ü, özellikle CPython-3.7.3 sürümünü desteklemektedir. Bu konu, Python 3 kullanarak kullanıcı tanımlı toplama işlevi (UDAF) nasıl yazılacağını açıklar.
UDAF kod yapısı
Kullanıcı tanımlı toplama işlevi (UDAF) kodunu Python 3 ile yazmak için MaxCompute Studio'ya giriş kılavuzunu kullanabilirsiniz. Kod aşağıdaki bilgileri içermelidir:
-
Modülleri içeri aktarma: Zorunludur.
En azından
from odps.udf import annotatevefrom odps.udf import BaseUDAFifadelerini içeri aktarmanız gerekir.from odps.udf import annotateifadesi, MaxCompute'in kodda tanımlanan işlev imzasını tanımasını sağlayan işlev imzası modülünü içeri aktarır.from odps.udf import BaseUDAFise Python UDAF'leri için temel sınıfı içeri aktarır. Türetilmiş sınıftaiterate,mergeveterminategibi yöntemleri uygulamanız gerekir.UDAF kodunun dosya veya tablo kaynaklarına başvurması gerekiyorsa, dosya kaynakları için
from odps.distcache import get_cache_fileveya tablo kaynakları içinfrom odps.distcache import get_cache_tableifadelerini ekleyin. -
İşlev imzası: Zorunludur.
Biçim
@annotate(<signature>)şeklindedir.signaturekısmı, işlevin giriş parametrelerinin ve dönüş değerinin veri türlerini tanımlar. İşlev imzaları hakkında daha fazla bilgi için bkz. İşlev imzası ve veri türleri. -
Özel Python sınıfı (türetilmiş sınıf): Zorunludur.
Bu sınıf, UDAF kodunun organizasyonel birimidir. İş mantığınızı uygulayan değişkenleri ve yöntemleri tanımlar. Kodunuzda yerleşik üçüncü taraf kitaplıklara, dosyalara veya tablo kaynaklarına da başvurabilirsiniz. Daha fazla bilgi için bkz. Üçüncü taraf kitaplıklar veya Kaynaklara başvurma.
-
Python sınıf yöntemlerini uygulama: Zorunludur.
Python sınıfı uygulaması aşağıdaki yöntemleri içerir. Yöntemleri ihtiyaca göre uygulayabilirsiniz.
Yöntem tanımı Açıklama BaseUDAF.new_buffer()Toplama işlevinin ara değeri için bir arabellek döndürür. bufferbir LIST veya DICT gibi bir Marshal nesnesi olmalıdır.bufferboyutu veri hacmiyle birlikte artmamalıdır. Aşırı durumlarda, nesne serileştirildikten sonrakibufferboyutu 2 MB'yi aşmamalıdır.BaseUDAF.iterate(buffer[, args, ...])argsparametrelerini ara değerbufferiçine toplar.BaseUDAF.merge(buffer, pbuffer)Ara değerler olan buffervepbufferöğelerini birleştirir ve sonucubufferiçinde saklar.BaseUDAF.terminate(buffer)bufferöğesini MaxCompute SQL'in ilkel veri türüne dönüştürür.
Aşağıdaki kod bir UDAF örneği sunar.
# Import the function signature module and the base class.
from odps.udf import annotate
from odps.udf import BaseUDAF
# Function signature.
@annotate('double->double')
# Custom Python class.
class Average(BaseUDAF):
# Implement the methods of the Python class.
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]
Aşağıdaki şekil, ortalama değeri (
avg
) hesaplayan bir MaxCompute UDAF'in uygulama mantığını ve hesaplama akışını gösterir.

Şekildeki
pr
değeri
pbuffer
'a,
r
değeri ise
buffer
'a karşılık gelir.
Python 2 UDAF'leri ile Python 3 UDAF'leri arasındaki fark, temel alınan Python sürümüdür. UDAF'inizi ilgili Python sürümünün yeteneklerine göre yazmalısınız.
Kullanım notları
Python 3, Python 2 ile uyumlu değildir ve her ikisi de aynı SQL deyimi içinde kullanılamaz. Geçiş yapmadan önce uyumluluğu göz önünde bulundurun.
Python 2, 2020 başında kullanım ömrünün sonuna (EOL) ulaşmıştır. Projelerinizi türlerine göre geçirmenizi öneririz.
Python 2 UDAF geçişi
Python Software Foundation, Python 2 desteğini yakında sonlandıracaktır. Projelerinizi proje türüne göre geçirmenizi öneririz:
Yeni projeler: Bu durum, yeni MaxCompute projeleri veya ilk kez Python UDAF yazdığınız MaxCompute projeleri için geçerlidir. Tüm Python UDAF'lerini Python 3 ile yazmanızı öneririz.
-
Mevcut projeler: Bu durum, çok sayıda mevcut Python 2 UDAF'i bulunan MaxCompute projeleri için geçerlidir. Python 3'ü dikkatli bir şekilde etkinleştirin. Tüm Python 2 UDAF'lerini Python 3'e kademeli olarak geçirmeyi planlıyorsanız aşağıdaki yöntemleri kullanın:
Yeni işler ve yeni UDAF'ler: Bunları Python 3 ile yazın ve Python 3'ü oturum düzeyinde etkinleştirin. Python 3'ün nasıl etkinleştirileceği hakkında daha fazla bilgi için bkz. Python 3'ü etkinleştirme.
-
Python 2 UDAF'leri: Python 2 UDAF'lerini hem Python 2 hem de Python 3 ile uyumlu olacak şekilde yeniden yazın. Kodun nasıl yeniden yazılacağı hakkında daha fazla bilgi için bkz. Python 2 Kodunu Python 3'e Taşıma.
NotGenel bir UDAF yazmak ve bunu birden fazla MaxCompute projesinin kullanması için izin vermek istiyorsanız, UDAF'in hem Python 2 hem de Python 3 ile uyumlu olmasını öneririz.
Python 3'ü etkinleştirme
MaxCompute varsayılan olarak Python 2 kullanır. Python 3 kullanmak için SQL deyiminize aşağıdaki oturum bayrağını ekleyin.
set odps.sql.python.version=cp37;
Üçüncü taraf kitaplıklar
MaxCompute'teki yerleşik Python 3 çalışma zamanı ortamında NumPy üçüncü taraf kitaplığı yüklü değildir. NumPy gerektiren bir UDAF kullanmak için NumPy WHEEL paketini manuel olarak yüklemeniz gerekir. NumPy paketini PyPI'den veya bir yansıdan indirirken, paket dosya adı numpy-<sürüm_numarası>-cp37-cp37m-manylinux1_x86_64.whl şeklinde olur. Paket yükleme hakkında daha fazla bilgi için bkz. Kaynak işlemleri veya UDF örneği: Python UDF'de üçüncü taraf paket kullanma.
İşlev imzası ve veri türleri
İşlev imzası aşağıdaki biçime sahiptir.
@annotate(<signature>)
signature
, giriş parametrelerinin ve dönüş değerinin veri türlerini tanımlayan bir dizedir. Bir UDAF çalıştırdığınızda, giriş parametrelerinin ve dönüş değerinin veri türleri işlev imzasında belirtilen türlerle eşleşmelidir. Sorgu ayrıştırma aşamasında sistem, işlev çağrısını işlev imzasına göre doğrular. Tür uyuşmazlığı bulunursa bir hata bildirilir. Belirli biçim aşağıdaki gibidir.
'arg_type_list -> type'
Burada:
-
arg_type_list: Giriş parametrelerinin veri türlerini temsil eder. Birden fazla giriş parametresi virgül (,) ile ayrılarak belirtilebilir. Desteklenen veri türleri BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(hassasiyet,ölçek), CHAR, VARCHAR, karmaşık veri türleri (ARRAY, MAP, STRUCT) ve iç içe geçmiş karmaşık veri türleridir.arg_type_listayrıca yıldız işareti (*) veya boş dize ('') değerlerini de destekler.arg_type_listbir yıldız işareti (*) ise, işlevin herhangi bir sayıda giriş parametresini kabul ettiği anlamına gelir.arg_type_listboş bir dize ('') ise, işlevin giriş parametresi olmadığı anlamına gelir.
Resolve ek açıklamasının genişletilmiş sözdizimi hakkında daha fazla bilgi için bkz. UDAF'ler ve UDTF'ler için dinamik parametreler.
type: Dönüş değerinin veri türünü temsil eder. Bir UDAF yalnızca bir sütun döndürür. Desteklenen veri türleri arasında BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(hassasiyet,ölçek), karmaşık veri türleri (ARRAY, MAP, STRUCT) ve iç içe geçmiş karmaşık veri türleri bulunur.
UDAF kodu yazarken, MaxCompute projenizin veri türü sürümüne göre uygun veri türlerini seçin. Veri türü sürümleri ve her sürüm tarafından desteklenen veri türleri hakkında daha fazla bilgi için bkz.
.
Aşağıdakiler geçerli işlev imzalarıdır.
| İşlev imzası örneği | Açıklama |
@annotate('bigint,double->string') |
Giriş parametresi türleri BIGINT ve DOUBLE, dönüş değeri türü ise STRING'dir. |
@annotate('*->string') |
İşlev herhangi bir sayıda giriş parametresini kabul eder ve dönüş değeri türü STRING'dir. |
@annotate('->double') |
İşlevin giriş parametresi yoktur ve dönüş değeri türü DOUBLE'dır. |
@annotate('array<bigint>->struct<x:string, y:int>') |
Giriş parametresi türü ARRAY |
Python UDAF'inizdeki veri türlerinin MaxCompute tarafından desteklenen veri türleriyle tutarlı olduğundan emin olmak için doğru veri türü eşlemelerini kullanmanız gerekir. Aşağıdaki tabloda bu eşlemeler açıklanmaktadır.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Kaynaklara başvurma
Python UDAF'leri, odps.distcache modülünü kullanarak dosya ve tablo kaynaklarına başvurabilir.
-
odps.distcache.get_cache_file(resource_name): Belirtilen dosya kaynağı için dosya benzeri bir nesne döndürür.-
resource_nameSTRING türündedir ve mevcut MaxCompute projesindeki mevcut bir dosya kaynağının adıyla eşleşir. Dosya kaynağı adı geçersizse veya kaynak yoksa bir özel durum oluşturulur.NotBir UDAF'ten bir kaynağa erişmek için, UDAF'i oluştururken başvurulan kaynağı bildirmeniz gerekir. Aksi takdirde bir hata bildirilir.
Dönüş değeri dosya benzeri bir nesnedir. Bu nesneyi kullanmayı bitirdikten sonra, açık kaynak dosyasını serbest bırakmak için
closeyöntemini çağırın.
-
-
odps.distcache.get_cache_table(resource_name): Belirtilen tablo kaynağı için bir üreteç (generator) nesnesi döndürür.resource_nameSTRING türündedir ve mevcut MaxCompute projesindeki mevcut bir tablo kaynağının adıyla eşleşir. Tablo kaynağı adı geçersizse veya kaynak yoksa bir özel durum oluşturulur.Dönüş değeri GENERATOR türündedir. Arayan, tablo içeriğini almak için üreteci tarar. Her yineleme, tablodan bir kaydı dizi olarak döndürür.
Kullanım hakkında daha fazla bilgi için bkz. Kaynaklara başvurma (Python 3 UDF) ve Kaynaklara başvurma (Python 3 UDTF).
Kullanım notları
geliştirme akışı izlenerek bir Python 3 UDAF geliştirdikten sonra, bunu bir MaxCompute SQL deyimi içinde çağırabilirsiniz. Çağrı yöntemleri aşağıdaki gibidir:
Bir MaxCompute projesinde UDF kullanma: Yöntem, yerleşik işlevleri kullanmaya benzer. Kullanıcı tanımlı bir işlevi, yerleşik bir işlevi kullandığınız şekilde kullanabilirsiniz.
Projeler arası UDF kullanma: B Projesindeki bir UDF'i A Projesinde kullanma. Aşağıdaki deyim bir örnek gösterir:
select B:udf_in_other_project(arg0, arg1) as res from table_t;. Projeler arası paylaşım hakkında daha fazla bilgi için bkz. Paketlere dayalı projeler arası kaynak erişimi.
MaxCompute Studio kullanarak bir Python 3 UDAF geliştirme ve çağırma prosedürünün tamamı için bkz. Python UDF Geliştirme.
UDAF'ler için dinamik parametreler
İşlev imzası
Python UDAF işlev imzası biçimi hakkında daha fazla bilgi için bkz. İşlev imzası ve veri türleri.
-
Herhangi bir sayıda ve türde giriş parametresini kabul etmek için parametre listesinde yıldız işareti (
*) kullanabilirsiniz. Örneğin,@annotate('double,*->string')ifadesi, ilk parametrenin DOUBLE türünde olduğunu, ardından herhangi bir sayıda ve türde parametre listesinin geldiğini belirtir. Bu durumda, giriş parametrelerinin sayısını ve türlerini belirlemek ve ardından bunlarda ilgili işlemleri gerçekleştirmek için kod yazmanız gerekir. Bu durum, C dilindekiprintfişlevine benzer.NotYıldız işaretinin (
*) dönüş değeri listesinde kullanıldığında farklı bir anlamı vardır. -
Bir UDTF'nin dönüş değerinde herhangi bir sayıda STRING türü dönüş değerini belirtmek için yıldız işareti (
*) kullanabilirsiniz. Dönüş değerlerinin sayısı, işlev çağrılırken ayarlanan takma adların sayısına bağlıdır. Örneğin,@annotate("bigint,string->double,*")için çağrı yöntemiUDTF(x, y) as (a, b, c)şeklindedir. Bu örnekte,asanahtar kelimesinden sonra üç takma ad ayarlanmıştır:a,bvec. Düzenleyici,adeğerini DOUBLE türünde kabul eder çünkü dönüş değerindeki ilk sütunun türü ek açıklamada belirtilmiştir;bvecdeğerlerini ise STRING türünde kabul eder. Üç dönüş değeri belirtildiğinden, UDTFforwardyöntemini çağırdığında,forwarduzunluğu 3 olan bir dizi olmalıdır. Aksi takdirde bir çalışma zamanı hatası oluşur.NotBu tür bir hata derleme zamanında bildirilemez. Bu nedenle, UDTF çağran kişi SQL deyimi içinde takma adların sayısını ayarlarken UDTF tarafından tanımlanan kurallara uymalıdır. Bir toplama işlevi için dönüş değeri sayısı 1 olarak sabitlendiğinden, bu özellik bir UDAF için geçerli değildir.
UDAF örneği
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])
Bir UDAF yalnızca bir dönüş değerine sahip olabilir. Yukarıdaki UDAF örneğinde, dönüş değeri birden fazla giriş parametresinin toplamıdır ve bu toplam birden fazla satır genelinde toplanır. Aşağıdaki kod bir kullanım örneği sunar.
-- Sums multiple input parameters.
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);
-- The return value is 55.