为本地文件夹准备已配置的 Snowflake Native App 工件¶
创建一个本地文件夹,其中包含已配置的工件¶
snow app bundle
命令会在您的项目中创建一个本地目录,使用您在项目定义文件中指定的文件结构填充该目录,并从包含装饰器(如 @sproc
或 @udaf
)的 Snowpark Python 代码在 Snowflake Native App 安装脚本中生成 CREATE FUNCTION 或 CREATE PROCEDURE 声明。有关更多信息,请参阅与所选函数装饰器相对应的 Snowpark Python 文档,如 snowflake.snowpark.functions.udaf。
snow app deploy
和 snow app run
命令已经使用了这一功能。不过,现在有了明确的 snow app bundle
命令在手,您可以在上传到暂存区之前探索该目录,以验证是否按预期创建了工件。
要创建包含已配置工件的本地文件夹,请执行以下操作:
创建或验证您的 Snowflake
snowflake.yml
项目定义文件,例如:definition_version: 2 entities: codegen_nativeapp_pkg: type: application package manifest: root_files/_manifest.yml artifacts: - src: root_files/README.md dest: README.md - src: root_files/_manifest.yml dest: manifest.yml - src: root_files/setup_scripts/* dest: setup_scripts/ - src: python/user_gen/echo.py dest: user_gen/echo.py - src: python/cli_gen/* dest: cli_gen/ processors: - snowpark codegen_nativeapp_pkg: type: application from: target: codegen_nativeapp_pkg
在项目目录下运行
snow app bundle
命令,创建包含已配置工件的临时output/deploy
目录。snow app bundle
验证输出或部署目录的内容是否符合您在 snowflake.yml. 文件中指定的规则。如果您在 Python 文件中调用了 Snowpark 注释处理,您可以在目录中的修正安装脚本中看到生成的代码。
有关更多信息,请参阅 snow app bundle 命令。
使用 Snowpark 注释处理生成 SQL 代码¶
作为 Snowflake Native App 开发人员,如果您的 SQL 背景有限,您可能会发现编写和维护 安装脚本 非常麻烦,随着时间的推移,脚本可能会变得相当庞大和复杂。安装脚本包含客户可使用其数据应用程序的所有应用逻辑,因此是开发 Snowflake Native App 的必要组成部分。安装脚本的核心组件之一是您可以将 Snowpark Python 扩展函数用于函数和存储过程。除了用 Python、Java 或其他 Snowpark 支持的语言编写 Snowpark 代码外,还需要在安装脚本中使用 SQL 编写这些函数和过程的相应部分。
例如,您可以使用 Snowpark Python 创建基本函数和存储过程,如下所示:
# Example python file "echo.py" that a developer writes
def echo_fn(data):
return 'echo_fn: ' + data
def echo_proc(session, data):
return 'echo_proc: ' + data
然后,您需要将该文件上传到暂存区,并从安装脚本 SQL 代码中引用该文件,类似于以下内容:
-- Sample setup_script.sql SQL file for a Snowflake Native App
CREATE APPLICATION ROLE IF NOT EXISTS app_instance_role;
CREATE OR ALTER VERSIONED SCHEMA ext_code_schema;
GRANT USAGE ON SCHEMA ext_code_schema TO APPLICATION ROLE app_instance_role;
CREATE OR REPLACE PROCEDURE ext_code_schema.py_echo_proc(DATA string)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = 3.9
PACKAGES=('snowflake-snowpark-python')
HANDLER='echo.echo_proc'
IMPORTS=('/echo.py');
GRANT USAGE ON PROCEDURE ext_code_schema.py_echo_proc(string)
TO APPLICATION ROLE app_instance_role;
-- Wraps a function from a python file
CREATE OR REPLACE FUNCTION ext_code_schema.py_echo_fn(string)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = 3.9
PACKAGES=('snowflake-snowpark-python')
HANDLER='echo.echo_fn'
IMPORTS=('/echo.py');
GRANT USAGE ON FUNCTION ext_code_schema.py_echo_fn(DATA string)
TO APPLICATION ROLE app_instance_role;
SQL 代码自动生成¶
备注
要利用 SQL 代码自动生成功能,您必须使用 Snowpark Python 1.15.0 及以上版本。
为了帮助减轻这些额外的工作,Snowflake CLI 可以为您的安装脚本自动生成必要的 SQL。Snowpark Python 支持一种称为扩展函数装饰器(@udf
、@sproc
、@udtf
和 @udaf
)的功能,让您可以对 Python 代码进行注释,例如使用 snowflake.snowpark.functions.udf 函数装饰器。Snowflake CLI 可以使用这些装饰器为安装脚本自动创建和验证必要的 SQL 代码。
例如,您可以为上一个示例中的函数使用 @udf
装饰器:
# some python file echo.py
@udf(name="echo_fn")
def echo_fn(data) -> str:
return 'echo_fn: ' + str
使用 @udf
装饰器会告诉 Snowflake CLI snow app bundle <../command-reference/native-apps-commands/bundle-app>`(以及其他内部调用 :codenowrap:`snow app bundle 命令的命令)处理 Snowpark Python 装饰器,生成相应的 SQL 命令,并将其自动包含在安装脚本中,如下所示。因此,您可以尽量减少安装脚本所需的 SQL 代码量。
-- Sample setup_script.sql SQL file for a Snowflake Native App
-- User-written code
CREATE OR REPLACE APPLICATION ROLE app_instance_role;
CREATE OR ALTER VERSIONED SCHEMA ext_code_schema;
GRANT USAGE ON SCHEMA ext_code_schema TO APPLICATION ROLE app_instance_role;
-- Snowflake CLI generated code
CREATE OR REPLACE FUNCTION ext_code_schema.py_echo_fn(DATA string)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = 3.9
PACKAGES=('snowflake-snowpark-python')
HANDLER='echo.echo_fn'
IMPORTS=('/echo.py');
GRANT USAGE ON FUNCTION ext_code_schema.py_echo_fn(string)
TO APPLICATION ROLE app_instance_role;
使用 Snowpark Python 装饰器¶
虽然 Snowflake CLI 中的 Snowpark 装饰器与普通的 Snowpark Python 装饰器工作原理相同,但为 Snowflake Native App 专门编写 Python 代码文件时,您应该注意以下区别:
您无法在这些文件中使用任何
Session
对象,因为 Snowflake CLI 是在与 Snowflake 无关的沙盒环境中执行这些 Python 文件的。因此,任何对 SnowparkSession
的引用都会导致错误。您只能使用
@udf
、@sproc
@udaf
和@udtf
Snowpark Python 装饰器。您无法将这些装饰器用作常规函数,以将您的代码注册为 Snowflake 对象。只有明确注释了支持的装饰器的代码才能被识别。因此,Python 函数必须是一个命名函数。不支持 Lambda 函数。
Snowflake CLI 始终会按照 Snowflake 的建议生成 CREATE OR REPLACE 语句,用于在安装脚本中创建函数和过程。
装饰器属性的更多信息¶
下表列出了 Python 装饰器属性,并解释了 Snowflake CLI 如何使用这些属性。
属性 |
详细信息 |
---|---|
name 可选 |
用于生成 SQL 语句的函数或存储过程 Snowflake CLI 的名称。 如果省略此属性,Snowflake CLI 将重复使用 Python 函数名来生成 SQL 语句。 |
input_types 必填 |
此函数或存储过程的每个输入参数的类型。 您必须在此装饰器参数中提供此信息,或直接在代码中提供类型注释。如果这两个位置都没有该信息,Snowflake CLI 就不会为此函数或存储过程生成 SQL 语句。 |
return_type 必填 |
此函数或存储过程的返回值类型。 您必须在此装饰器参数中提供此信息,或直接在代码中提供类型注释。如果这两个位置都没有该信息,Snowflake CLI 就不会为此函数或存储过程生成 SQL 语句。 |
packages 可选 |
包列表。您可以指定 如果省略此属性,Snowflake CLI 会自动添加 |
imports 可选 |
您的 Snowflake 函数或存储过程需要从暂存区导入的文件列表。您可以以字符串或字符串元组的形式指定它们。如果指定元组,Snowflake CLI 只使用第 0 个索引处的字符串。有关使用元组的示例,请参阅 使用外部 Python 文件。 如果没有指定任何导入,Snowflake CLI 会自动为包含函数或存储过程的 Python 文件添加导入,并为其生成 SQL。导入路径由部署根目录中 Python 文件的 |
execute_as 可选 |
执行存储过程时使用的角色。值包括: |
handler 不适用 |
函数或存储过程的处理程序。Snowflake CLI 会自动填充此字段。 |
replace 未使用 |
Snowflake CLI 假定 |
session 必填 |
必须是 ``None``如果省略,Snowflake CLI 会引发错误。 |
is_permanent 未使用 |
生成 SQL 时,Snowflake CLI 不使用此字段。 |
stage_location 未使用 |
生成 SQL 时,Snowflake CLI 不使用此字段。 |
if_not_exists 未使用 |
生成 SQL 时,Snowflake CLI 不使用此字段。 |
strict 未使用 |
生成 SQL 时,Snowflake CLI 不使用此字段。 |
secure 未使用 |
生成 SQL 时,Snowflake CLI 不使用此字段。 |
immutable 未使用 |
生成 SQL 时,Snowflake CLI 不使用此字段。 |
native_app_params 可选 |
(仅适用于 Snowflake Native App) 包含以下 Snowflake Native App 参数的 Python 字典:
虽然在技术上是可选的,但如果不在项目定义文件中指定 |
将 Python 文件上传到目标暂存区时,Snowflake CLI 会将装饰器转换为注释,因此这些 UDFs 和存储过程不会在当前会话中创建。原始源文件不会被更改,因此 snow app bundle
命令仍然具有幂等性。由于每次运行 snow app bundle
命令时都会重新创建部署根目录,因此只有部署根目录中的 Python 文件才会包含注释。下面的示例说明了 Snowflake CLI 如何对装饰器添加注释。
# output/deploy/dest_dir1/dest_dir2/echo.py
#: @sproc(
#: return_type=IntegerType(),
#: input_types=[IntegerType(), IntegerType()],
#: packages=["snowflake-snowpark-python==1.15.0"],
#: native_app_params={
#: "schema": "ext_code_schema",
#: "application_roles": ["app_instance_role"],
#: },
#: )
def add_sp(session_, x, y):
return x + y
此外,只有在项目定义文件中带有 processors
属性的 Python 文件才会受到影响。