Python UDFsの作成

このトピックでは、Python UDF(ユーザー定義関数)を作成してインストールする方法を示します。

このトピックの内容:

Pythonコードの記述

Pythonモジュールと関数の記述

以下の仕様に従うモジュールを作成します。

  • モジュールを定義します。モジュールは、Pythonの定義とステートメントを含むファイルです。

  • モジュール内で関数を定義します。

  • 関数が引数を受け入れる場合、各引数は SQL-Python型マッピングテーブルPython Data Type 列で指定されたデータ型の1つである必要があります。

    関数引数は、名前ではなく位置によってバインドされます。UDFに渡される最初の引数は、Python関数が最初に受け取る引数です。

  • 適切な戻り値を指定します。Python UDFはスカラー関数である必要があるため、呼び出されるたびに1つの値を返す必要があります。戻り値の型は、 SQL-Python型マッピングテーブルPython Data Type 列で指定されたデータ型の1つである必要があります。戻り値の型は、 CREATE FUNCTION ステートメントの RETURNS 句で指定されたSQLデータ型と互換性がある必要があります。

  • モジュールには複数の関数を含めることができます。Snowflakeによって呼び出される関数は、同じモジュールまたは他のモジュール内の他の関数を呼び出すことができます。

  • 関数(および関数によって呼び出される関数)は、 Python UDFs に対してSnowflakeが課す制約 に準拠する必要があります。

注釈

ベクトル化されたPython UDFs を使用すると、入力行のバッチを Pandas DataFrames として受け取り、結果のバッチを Pandas配列 または Series として返すPython関数を定義します。詳細については、 ベクトル化されたPython UDFs をご参照ください。

Snowflakeでの関数の作成

次を指定するには、 CREATE FUNCTION ステートメントを実行する必要があります。

  • UDF に使用する名前。

  • Python UDFが呼び出されたときに呼び出すPython関数の名前。

UDFの名前は、Pythonで記述されたハンドラー関数の名前と一致する必要はありません。Python関数を使用した UDF 名を関連付ける CREATE FUNCTION ステートメントにある HANDLER 句。

UDF の名前を選択する場合は、 プロシージャおよび UDFs の命名とオーバーロード をご参照ください。

CREATE FUNCTION ステートメントの本文内では、関数の引数は名前ではなく位置によってバインドされます。CREATE FUNCTION ステートメントで宣言された最初の引数は、Python関数に渡される最初の引数です。

引数のデータ型については、 SQL-Pythonデータ型マッピング をご参照ください。

runtime_version をコードに必要なPythonランタイムのバージョンに設定します。サポートされているPythonのバージョンは次のとおりです。

  • 3.8

  • 3.9

  • 3.10

インラインコードを使用するUDFsとステージからアップロードされたコードを使用するUDFsの対比

Python UDFのコードは、次のいずれかの方法で指定できます。

  • ステージからアップロード: CREATE FUNCTIONステートメントは、 ステージ 内の既存のPythonソースコードの場所を指定します。

  • インライン: CREATE FUNCTIONステートメントは、Pythonソースコードを指定します。

インラインPython UDFの作成

インライン UDFの場合は、CREATEFUNCTIONステートメントの一部としてPythonソースコードを提供します。

たとえば、次のステートメントは、指定された整数に1を追加するインラインPython UDFを作成します。

create or replace function addone(i int)
returns int
language python
runtime_version = '3.8'
handler = 'addone_py'
as
$$
def addone_py(i):
  return i+1
$$;
Copy

Pythonソースコードは AS 句で指定されます。ソースコードは、一重引用符またはドル記号($$)のペアで囲むことができます。ソースコードに一重引用符が埋め込まれている場合は、通常、二重ドル記号を使用する方が簡単です。

UDF を呼び出します。

select addone(10);
Copy

出力は次のとおりです。

+------------+
| ADDONE(10) |
|------------|
|         11 |
+------------+
Copy

Pythonソースコードには複数のモジュールとモジュール内の複数の関数を含めることができるため、 HANDLER 句は呼び出すモジュールと関数を指定します。

インラインPython UDFは、 IMPORTS 句に含まれるモジュールのコードを呼び出すことができます。

CREATE FUNCTION ステートメントの構文の詳細については、 CREATE FUNCTION をご参照ください。

その他の例については、 インラインPython UDFの例 をご参照ください。

ステージからアップロードされたコードを使用したPython UDFの作成

次のステートメントは、 ステージ からアップロードされたコードを使用して単純なPython UDFを作成します。ファイルをホストするステージは、UDFの 所有者 によって読み取り可能である必要があります。また、ZIPファイルは自己完結型である必要があり、実行する追加のセットアップスクリプトに依存しないようにする必要があります。

ソースコードを含む sleepy.py という名前のPythonファイルを作成します。

def snore(n):   # return a series of n snores
    result = []
    for a in range(n):
        result.append("Zzz")
    return result
Copy

SnowSQL (CLI クライアント) を起動し、 PUT コマンドを使用して、ファイルをローカルファイルシステムから @~ という名前のデフォルトのユーザーステージにコピーします。(PUT コマンドは、Snowflake GUIで実行できないことに注意してください。)

put
file:///Users/Me/sleepy.py
@~/
auto_compress = false
overwrite = true
;
Copy

ファイルを削除または名前変更すると、UDFを呼び出すことができなくなります。ファイルを更新する必要がある場合はファイルを更新できますが、更新中はUDFを呼び出すことができません。古いファイルがまだステージにある場合、 PUT コマンドには OVERWRITE=TRUE 句を含める必要があります。

UDFを作成します。ハンドラーはモジュールと関数を指定します。

create or replace function dream(i int)
returns variant
language python
runtime_version = '3.8'
handler = 'sleepy.snore'
imports = ('@~/sleepy.py')
Copy

UDF を呼び出します。

select dream(3);

+----------+
| DREAM(3) |
|----------|
| [        |
|   "Zzz", |
|   "Zzz", |
|   "Zzz"  |
| ]        |
+----------+
Copy

複数のインポートファイルの指定

複数のインポートファイルを指定する方法の例を次に示します。

create or replace function multiple_import_files(s string)
returns string
language python
runtime_version=3.8
imports=('@python_udf_dep/bar/python_imports_a.zip', '@python_udf_dep/foo/python_imports_b.zip')
handler='compute'
as
$$
def compute(s):
  return s
$$;
Copy

注釈

指定されたインポートファイル名は異なっている必要があります。例えば、これは機能しません: imports=('@python_udf_dep/bar/python_imports.zip', '@python_udf_dep/foo/python_imports.zip')

関数に対する権限の付与

関数の所有者以外のロールが関数を呼び出すには、所有者がそのロールに適切な権限を付与する必要があります。

Python UDFの GRANT ステートメントは、JavaScript UDFsなどといった、他のUDFsのGRANTステートメントと基本的に同じです。

例:

GRANT USAGE ON FUNCTION my_python_udf(number, number) TO my_role;
Copy