פונקציות בהגדרת המשתמש ב-Python

פונקציה בהגדרת המשתמש (UDF) ב-Python מאפשרת להטמיע פונקציה סקלרית ב-Python ולהשתמש בה בשאילתת SQL. פונקציות בהגדרת המשתמש (UDF) ב-Python דומות לפונקציות בהגדרת המשתמש ב-SQL וב-JavaScript, אבל יש להן יכולות נוספות. פונקציות UDF ב-Python מאפשרות לכם להתקין ספריות של צד שלישי מהאינדקס של חבילות Python‏ (PyPI) ולגשת לשירותים חיצוניים באמצעות חיבור למשאבי Cloud.

פונקציות UDF ב-Python נוצרות ומופעלות במשאבים מנוהלים של BigQuery.

מגבלות

  • python-3.11 היא סביבת זמן הריצה היחידה שנתמכת.
  • אי אפשר ליצור פונקציית UDF זמנית ב-Python.
  • אי אפשר להשתמש בפונקציה מוגדרת על ידי המשתמש (UDF) בשפת Python עם תצוגה מגובה בחומר.
  • התוצאות של שאילתה שמפעילה פונקציית UDF של Python לא נשמרות במטמון, כי ערך ההחזרה של פונקציית UDF של Python תמיד נחשב כלא דטרמיניסטי.
  • אין תמיכה מלאה בפונקציות מוגדרות על ידי המשתמש (UDF) ב-Python בתצוגות של INFORMATION_SCHEMA.
  • אי אפשר ליצור או לעדכן UDF ב-Python באמצעות Routine API.
  • אין תמיכה ב-VPC Service Controls.
  • אין תמיכה במפתחות הצפנה בניהול הלקוח (CMEK).
  • סוגי הנתונים הבאים לא נתמכים: JSON,‏ RANGE,‏ INTERVAL ו-GEOGRAPHY.
  • אפשר להגדיר קונטיינרים שמריצים פונקציות UDF של Python רק עד 2 vCpu ו-8 Gi.

התפקידים שצריך ב-IAM

התפקידים הנדרשים ב-IAM תלויים בשאלה אם אתם הבעלים של פונקציית Python UDF או משתמשים בפונקציית Python UDF. בדרך כלל, הבעלים של פונקציית UDF ב-Python יוצר או מעדכן פונקציית UDF. משתמש בפונקציה מוגדרת על ידי משתמש (UDF) ב-Python מפעיל פונקציה מוגדרת על ידי משתמש שנוצרה על ידי מישהו אחר.

נדרשים גם תפקידים נוספים אם יוצרים או מריצים פונקציית UDF ב-Python שמפנה לחיבור למשאב ב-Cloud.

בעלי UDF

אם אתם יוצרים או מעדכנים UDF של Python, צריך להקצות את תפקידי ה-IAM המוגדרים מראש הבאים במשאב המתאים:

תפקיד ההרשאות הנדרשות משאב
עריכה של נתוני BigQuery (roles/bigquery.dataEditor)
  • bigquery.routines.create כדי ליצור פונקציית UDF ב-Python באמצעות ההצהרה CREATE FUNCTION.
  • bigquery.routines.update כדי לעדכן פונקציית UDF של Python באמצעות ההצהרה CREATE FUNCTION.
מערך הנתונים שבו נוצר או מתעדכן ה-UDF של Python.
BigQuery Job User (roles/bigquery.jobUser)
  • bigquery.jobs.create כדי להריץ משימת שאילתה של הצהרה CREATE FUNCTION.
הפרויקט שבו מריצים את ההצהרה CREATE FUNCTION.
אדמין של חיבור ל-BigQuery (roles/bigquery.connectionAdmin) החיבור שדרכו אתם נותנים גישה למשאב חיצוני. החיבור הזה נדרש רק אם ה-UDF משתמש בסעיף WITH CONNECTION כדי לגשת לשירות חיצוני.

משתמשים ב-UDF

אם אתם מפעילים UDF של Python, צריך להעניק את תפקידי ה-IAM המוגדרים מראש הבאים במשאב המתאים:

תפקיד ההרשאות הנדרשות משאב
BigQuery User (roles/bigquery.user) bigquery.jobs.create כדי להריץ עבודת שאילתה שמפנה אל הפונקציה המוגדרת על ידי המשתמש. הפרויקט שבו מריצים עבודת שאילתה שמפעילה את פונקציית ה-UDF של Python.
BigQuery Data Viewer (roles/bigquery.dataViewer) bigquery.routines.get כדי להפעיל פונקציה מוגדרת על ידי המשתמש שנוצרה על ידי מישהו אחר. מערך הנתונים שבו מאוחסנת פונקציית ה-UDF של Python.
BigQuery Connection User (roles/bigquery.connectionUser) bigquery.connections.use להפעלת פונקציית UDF של Python שמפנה לחיבור של משאב Cloud. החיבור למשאב בענן שאליו מתייחסת פונקציית Python UDF. החיבור הזה נדרש רק אם הפונקציה המוגדרת על ידי המשתמש מפנה לחיבור.

מידע נוסף על תפקידים ב-BigQuery זמין במאמר תפקידים מוגדרים מראש ב-IAM.

יצירת פונקציה מתמידה מוגדרת על ידי המשתמש (UDF) ב-Python

כשיוצרים פונקציית UDF ב-Python, צריך לפעול לפי הכללים הבאים:

  • הגוף של פונקציית Python UDF חייב להיות ליטרל מחרוזת בתוך מרכאות שמייצג את קוד Python. מידע נוסף על פורמטים של ליטרלים במירכאות

  • גוף הפונקציה המוגדרת על ידי המשתמש ב-Python חייב לכלול פונקציית Python שמשמשת בארגומנט entry_point ברשימת האפשרויות של הפונקציה המוגדרת על ידי המשתמש ב-Python.

  • צריך לציין גרסת זמן ריצה של Python באפשרות runtime_version. גרסת זמן הריצה היחידה של Python שנתמכת היא python-3.11. רשימה מלאה של האפשרויות הזמינות מופיעה ברשימת האפשרויות של הפונקציה עבור הצהרת CREATE FUNCTION.

כדי ליצור פונקציית UDF מתמשכת ב-Python, משתמשים בהצהרה CREATE FUNCTION בלי מילות המפתח TEMP או TEMPORARY. כדי למחוק פונקציית Python UDF מתמידה, משתמשים בהצהרה DROP FUNCTION.

כשיוצרים פונקציה מוגדרת על ידי המשתמש (UDF) ב-Python באמצעות ההצהרה CREATE FUNCTION,‏ BigQuery יוצר או מעדכן קובץ אימג' של קונטיינר שמבוסס על קובץ אימג' בסיסי. הקונטיינר נוצר על בסיס תמונת הבסיס באמצעות הקוד שלכם וכל תלות בחבילות שצוינה. יצירת המאגר היא תהליך ארוך. יכול להיות שהשאילתה הראשונה אחרי הפעלת ההצהרה CREATE FUNCTION תחכה אוטומטית עד שהתמונה תושלם. בדרך כלל, קובץ אימג' של קונטיינר נוצר תוך פחות מדקה, בלי תלות חיצונית.

דוגמה

כדי לראות דוגמה ליצירת פונקציית UDF מתמשכת ב-Python, בוחרים באחת מהאפשרויות הבאות:

המסוף

בדוגמה הבאה נוצרת פונקציה מתמידה בשפת Python בשם multiplyInputs, והפונקציה נקראת מתוך הצהרת SELECT:

  1. עוברים לדף BigQuery.

    כניסה ל-BigQuery

  2. מזינים את ההצהרה הבאה CREATE FUNCTION בעורך השאילתות:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.multiplyInputs(x FLOAT64, y FLOAT64)
    RETURNS FLOAT64
    LANGUAGE python
    OPTIONS(runtime_version="python-3.11", entry_point="multiply")
    AS r'''
    
    def multiply(x, y):
      return x * y
    
    ''';
    
    -- Call the Python UDF.
    WITH numbers AS
      (SELECT 1 AS x, 5 as y
      UNION ALL
      SELECT 2 AS x, 10 as y
      UNION ALL
      SELECT 3 as x, 15 as y)
    SELECT x, y,
    `PROJECT_ID.DATASET_ID`.multiplyInputs(x, y) AS product
    FROM numbers;

    החלפה של PROJECT_ID.‫DATASET_ID במזהה הפרויקט ובמזהה מערך הנתונים.

  3. לוחצים על  הפעלה.

    הדוגמה הזו יוצרת את הפלט הבא:

    +-----+-----+--------------+
    | x   | y   | product      |
    +-----+-----+--------------+
    | 1   | 5   |  5.0         |
    | 2   | 10  | 20.0         |
    | 3   | 15  | 45.0         |
    +-----+-----+--------------+
    

‫BigQuery DataFrames

בדוגמה הבאה נעשה שימוש ב-BigQuery DataFrames כדי להפוך פונקציה מותאמת אישית ל-UDF של Python:

import bigframes.pandas as bpd

# Set BigQuery DataFrames options
bpd.options.bigquery.project = your_gcp_project_id
bpd.options.bigquery.location = "US"

# BigQuery DataFrames gives you the ability to turn your custom functions
# into a BigQuery Python UDF. One can find more details about the usage and
# the requirements via `help` command.
help(bpd.udf)

# Read a table and inspect the column of interest.
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")
df["body_mass_g"].peek(10)

# Define a custom function, and specify the intent to turn it into a
# BigQuery Python UDF. Let's try a `pandas`-like use case in which we want
# to apply a user defined function to every value in a `Series`, more
# specifically bucketize the `body_mass_g` value of the penguins, which is a
# real number, into a category, which is a string.
@bpd.udf(
    dataset=your_bq_dataset_id,
    name=your_bq_routine_id,
)
def get_bucket(num: float) -> str:
    if not num:
        return "NA"
    boundary = 4000
    return "at_or_above_4000" if num >= boundary else "below_4000"

# Then we can apply the udf on the `Series` of interest via
# `apply` API and store the result in a new column in the DataFrame.
df = df.assign(body_mass_bucket=df["body_mass_g"].apply(get_bucket))

# This will add a new column `body_mass_bucket` in the DataFrame. You can
# preview the original value and the bucketized value side by side.
df[["body_mass_g", "body_mass_bucket"]].peek(10)

# The above operation was possible by doing all the computation on the
# cloud through an underlying BigQuery Python UDF that was created to
# support the user's operations in the Python code.

# The BigQuery Python UDF created to support the BigQuery DataFrames
# udf can be located via a property `bigframes_bigquery_function`
# set in the udf object.
print(f"Created BQ Python UDF: {get_bucket.bigframes_bigquery_function}")

# If you have already defined a custom function in BigQuery, either via the
# BigQuery Google Cloud Console or with the `udf` decorator,
# or otherwise, you may use it with BigQuery DataFrames with the
# `read_gbq_function` method. More details are available via the `help`
# command.
help(bpd.read_gbq_function)

existing_get_bucket_bq_udf = get_bucket.bigframes_bigquery_function

# Here is an example of using `read_gbq_function` to load an existing
# BigQuery Python UDF.
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")
get_bucket_function = bpd.read_gbq_function(existing_get_bucket_bq_udf)

df = df.assign(body_mass_bucket=df["body_mass_g"].apply(get_bucket_function))
df.peek(10)

# Let's continue trying other potential use cases of udf. Let's say we
# consider the `species`, `island` and `sex` of the penguins sensitive
# information and want to redact that by replacing with their hash code
# instead. Let's define another scalar custom function and decorate it
# as a udf. The custom function in this example has external package
# dependency, which can be specified via `packages` parameter.
@bpd.udf(
    dataset=your_bq_dataset_id,
    name=your_bq_routine_id,
    packages=["cryptography"],
)
def get_hash(input: str) -> str:
    from cryptography.fernet import Fernet

    # handle missing value
    if input is None:
        input = ""

    key = Fernet.generate_key()
    f = Fernet(key)
    return f.encrypt(input.encode()).decode()

# We can use this udf in another `pandas`-like API `map` that
# can be applied on a DataFrame
df_redacted = df[["species", "island", "sex"]].map(get_hash)
df_redacted.peek(10)

# If the BigQuery routine is no longer needed, we can clean it up
# to free up any cloud quota
session = bpd.get_global_session()
session.bqclient.delete_routine(f"{your_bq_dataset_id}.{your_bq_routine_id}")

יצירת פונקציה מוגדרת על ידי המשתמש (UDF) ב-Python עם וקטוריזציה

אפשר להטמיע את פונקציית ה-UDF של Python כדי לעבד קבוצה של שורות במקום שורה אחת, באמצעות וקטוריזציה. הפיכת נתונים לווקטורים יכולה לשפר את ביצועי השאילתות.

כדי לשלוט בהתנהגות של העיבוד באצווה, מציינים את המספר המקסימלי של שורות בכל אצווה באמצעות האפשרות max_batching_rows ברשימת האפשרויות CREATE OR REPLACE FUNCTION. אם מציינים max_batching_rows, ‏ BigQuery קובע את מספר השורות בחבילה, עד למגבלה של max_batching_rows. אם לא מציינים את max_batching_rows, מספר השורות שיש לצרף לחבילה נקבע באופן אוטומטי.

ל-UDF וקטורי ב-Python יש ארגומנט pandas.DataFrame אחד שחייב להיות עם הערה. לארגומנט pandas.DataFrame יש מספר עמודות זהה למספר הפרמטרים של פונקציית ה-UDF של Python שהוגדרו בהצהרה CREATE FUNCTION. לשמות העמודות בארגומנט pandas.DataFrame יש את אותם שמות כמו לפרמטרים של הפונקציה המוגדרת על ידי המשתמש.

הפונקציה צריכה להחזיר pandas.Series או pandas.DataFrame בעמודה אחת עם אותו מספר שורות כמו הקלט.

בדוגמה הבאה נוצרת פונקציית UDF וקטורית של Python בשם multiplyInputs עם שני פרמטרים – x ו-y:

  1. עוברים לדף BigQuery.

    כניסה ל-BigQuery

  2. בעורך השאילתות, מזינים את ההצהרה הבאה של CREATE FUNCTION:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.multiplyVectorized(x FLOAT64, y FLOAT64)
    RETURNS FLOAT64
    LANGUAGE python
    OPTIONS(runtime_version="python-3.11", entry_point="vectorized_multiply")
    AS r'''
    import pandas as pd
    
    def vectorized_multiply(df: pd.DataFrame):
      return df['x'] * df['y']
    
    ''';

    החלפה של PROJECT_ID.‫DATASET_ID במזהה הפרויקט ובמזהה מערך הנתונים.

    הקריאה לפונקציית ה-UDF זהה לקריאה בדוגמה הקודמת.

  3. לוחצים על  הפעלה.

סוגי נתונים נתמכים של פונקציות מוגדרות על ידי המשתמש (UDF) ב-Python

בטבלה הבאה מוגדר המיפוי בין סוגי נתונים ב-BigQuery, סוגי נתונים ב-Python וסוגי נתונים ב-Pandas:

סוג נתונים ב-BigQuery סוג נתונים מובנה ב-Python שמשמש פונקציות UDF רגילות סוג הנתונים של Pandas שמשמש את פונקציית ה-UDF הווקטורית סוג הנתונים של PyArrow שמשמש ל-ARRAY ול-STRUCT בפונקציות מוגדרות על ידי המשתמש (UDF) עם וקטוריזציה
BOOL bool BooleanDtype DataType(bool)
INT64 int Int64Dtype DataType(int64)
FLOAT64 float FloatDtype DataType(double)
STRING str StringDtype DataType(string)
BYTES bytes binary[pyarrow] DataType(binary)
TIMESTAMP

פרמטר של פונקציה: datetime.datetime (עם אזור הזמן UTC)

ערך ההחזרה של הפונקציה: datetime.datetime (עם הגדרת אזור זמן כלשהו)

פרמטר של פונקציה: timestamp[us, tz=UTC][pyarrow]

הערך המוחזר של הפונקציה: timestamp[us, tz=*][pyarrow]\(any timezone\)

TimestampType(timestamp[us]), עם אזור זמן
DATE datetime.date date32[pyarrow] DataType(date32[day])
TIME datetime.time time64[pyarrow] Time64Type(time64[us])
DATETIME datetime.datetime (ללא אזור זמן) timestamp[us][pyarrow] TimestampType(timestamp[us]), בלי אזור זמן
ARRAY list list<...>[pyarrow], כאשר סוג הנתונים של הרכיב הוא pandas.ArrowDtype ListType
STRUCT dict struct<...>[pyarrow], כאשר סוג הנתונים של השדה הוא pandas.ArrowDtype StructType

גרסאות זמן ריצה נתמכות

פונקציות UDF של Python ב-BigQuery תומכות בזמן הריצה python-3.11. גרסת Python הזו כוללת כמה חבילות נוספות שהותקנו מראש. בספריות מערכת, בודקים את תמונת הבסיס של זמן הריצה.

גרסת זמן ריצה גרסת Python כולל תמונת הבסיס בזמן הריצה
python-3.11 Python 3.11 ‫numpy 1.26.3
pyarrow 14.0.2
pandas 2.1.4
python-dateutil 2.8.2
google-22-full/python311

שימוש בחבילות של צד שלישי

אפשר להשתמש ברשימת האפשרויות CREATE FUNCTION כדי להשתמש במודולים אחרים מאלה שסופקו על ידי ספריית התקנים של Python ובחבילות שהותקנו מראש. אפשר להתקין חבילות מאינדקס החבילות של Python ‏ (PyPI), או לייבא קובצי Python מ-Cloud Storage.

התקנת חבילה מאינדקס חבילות Python

כשמתקינים חבילה, צריך לציין את שם החבילה, ואפשר גם לציין את גרסת החבילה באמצעות מצייני גרסאות של חבילות Python. אם החבילה נמצאת בסביבת זמן הריצה, נעשה בה שימוש אלא אם צוינה גרסה מסוימת ברשימת האפשרויות של CREATE FUNCTION. אם לא מציינים גרסת חבילה, והחבילה לא נמצאת בסביבת זמן הריצה, נעשה שימוש בגרסה העדכנית ביותר שזמינה. יש תמיכה רק בחבילות עם הפורמט הבינארי wheels.

בדוגמה הבאה אפשר לראות איך יוצרים פונקציית UDF ב-Python שמתקינה את חבילת scipy באמצעות רשימת האפשרויות CREATE OR REPLACE FUNCTION:

  1. עוברים לדף BigQuery.

    כניסה ל-BigQuery

  2. מזינים את ההצהרה הבאה CREATE FUNCTION בעורך השאילתות:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.area(radius FLOAT64)
    RETURNS FLOAT64 LANGUAGE python
    OPTIONS (entry_point='area_handler', runtime_version='python-3.11', packages=['scipy==1.15.3'])
    AS r"""
    import scipy
    
    def area_handler(radius):
      return scipy.constants.pi*radius*radius
    """;
    
    SELECT `PROJECT_ID.DATASET_ID`.area(4.5);

    החלפה של PROJECT_ID.‫DATASET_ID במזהה הפרויקט ובמזהה מערך הנתונים.

  3. לוחצים על  הפעלה.

ייבוא קובצי Python נוספים כספריות

אפשר להרחיב את הפונקציות המוגדרות על ידי המשתמש ב-Python באמצעות רשימת האפשרויות של הפונקציה על ידי ייבוא קובצי Python מ-Cloud Storage.

בקוד Python של הפונקציה המוגדרת על ידי המשתמש, אפשר לייבא את קובצי ה-Python מ-Cloud Storage כמודולים באמצעות הצהרת הייבוא, ואחריה הנתיב לאובייקט Cloud Storage. לדוגמה, אם מייבאים את gs://BUCKET_NAME/path/to/lib1.py, הצהרת הייבוא תהיה import path.to.lib1.

שם הקובץ ב-Python צריך להיות מזהה ב-Python. כל שם של folder בשם האובייקט (אחרי /) צריך להיות מזהה תקין ב-Python. בטווח ASCII ‏ (U+0001..U+007F), אפשר להשתמש בתווים הבאים במזהים:

  • אותיות קטנות וגדולות באנגלית, מ-A עד Z.
  • קווים תחתונים.
  • הספרות אפס עד תשע, אבל מספר לא יכול להופיע כתו הראשון במזהה.

בדוגמה הבאה מוצג איך ליצור פונקציית UDF ב-Python שמייבאת את חבילת ספריית הלקוח lib1.py מקטגוריה של Cloud Storage בשם my_bucket:

  1. עוברים לדף BigQuery.

    כניסה ל-BigQuery

  2. מזינים את ההצהרה הבאה CREATE FUNCTION בעורך השאילתות:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.myFunc(a FLOAT64, b STRING)
    RETURNS STRING LANGUAGE python
    OPTIONS (
    entry_point='compute', runtime_version='python-3.11',
    library=['gs://my_bucket/path/to/lib1.py'])
    AS r"""
    import path.to.lib1 as lib1
    
    def compute(a, b):
      # doInterestingStuff is a function defined in
      # gs://my_bucket/path/to/lib1.py
      return lib1.doInterestingStuff(a, b);
    
    """;

    החלפה של PROJECT_ID.‫DATASET_ID במזהה הפרויקט ובמזהה מערך הנתונים.

  3. לוחצים על  הפעלה.

הגדרת מגבלות קונטיינר לפונקציות מוגדרות על ידי המשתמש (UDF) ב-Python

אפשר להשתמש ברשימת האפשרויות CREATE FUNCTION כדי לציין מגבלות על השימוש במעבד ובזיכרון עבור קונטיינרים שמריצים פונקציות UDF של Python.

כברירת מחדל, הזיכרון שמוקצה לכל מופע של קונטיינר הוא ‎512 MiB, והמעבד (CPU) שמוקצה הוא ‎1.0 vCPU.

בדוגמה הבאה נוצרת פונקציית UDF של Python באמצעות רשימת האפשרויות CREATE FUNCTION כדי לציין מגבלות על הקונטיינר:

  1. עוברים לדף BigQuery.

    כניסה ל-BigQuery

  2. מזינים את ההצהרה הבאה CREATE FUNCTION בעורך השאילתות:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.resizeImage(image BYTES)
    RETURNS BYTES LANGUAGE python
    OPTIONS (entry_point='resize_image', runtime_version='python-3.11',
    packages=['Pillow==11.2.1'], container_memory='2Gi', container_cpu=1)
    AS r"""
    import io
    from PIL import Image
    
    def resize_image(image_bytes):
      img = Image.open(io.BytesIO(image_bytes))
    
      resized_img = img.resize((256, 256), Image.Resampling.LANCZOS)
      output_stream = io.BytesIO()
      resized_img.convert('RGB').save(output_stream, format='JPEG')
      return output_stream.getvalue()
    """;

    החלפה של PROJECT_ID.‫DATASET_ID במזהה הפרויקט ובמזהה מערך הנתונים.

  3. לוחצים על  הפעלה.

ערכי מעבד נתמכים

פונקציות UDF ב-Python תומכות בערכי CPU חלקיים בין 0.33 ל-1.0 ובערכי CPU לא חלקיים של 1 ו-2. ערכים חלקיים של קלט מעוגלים לשתי ספרות אחרי הנקודה העשרונית לפני שהם מוחלים על מאגר התגים.

ערכי זיכרון נתמכים

מאגרי Python UDF תומכים בערכי זיכרון בפורמט הבא: <integer_number><unit>. היחידה צריכה להיות אחת מהערכים הבאים: Mi, ‏ M, ‏ Gi,‏ G. כמות הזיכרון המינימלית שאפשר להגדיר היא 256 מביבייט (256 Mi). כמות הזיכרון המקסימלית שאפשר להגדיר היא 8 גיביבייט (8 Gi).

בהתאם לערך הזיכרון שתבחרו, תצטרכו גם לציין את כמות המינימום של CPU. בטבלה הבאה מוצגים ערכי ה-CPU המינימליים לכל ערך זיכרון:

זיכרון מעבד מינימלי
512 MiB or less 0.33
More than 512 MiB 0.5
More than 1 GiB 1
More than 4 GiB 2

התקשרות Cloud de Confiance by S3NS לשירותים באינטרנט בקוד Python

פונקציית UDF ב-Python ניגשת לשירות Cloud de Confiance by S3NS או לשירות חיצוני באמצעות חשבון השירות של חיבור משאבי Cloud. צריך להעניק לחשבון השירות של החיבור הרשאות גישה לשירות. ההרשאות הנדרשות משתנות בהתאם לשירות שאליו ניגשים ולממשקי ה-API שמבוצעת אליהם קריאה מהקוד שלכם ב-Python.

אם יוצרים פונקציית UDF ב-Python בלי להשתמש בחיבור למשאב Cloud, הפונקציה מופעלת בסביבה שחוסמת גישה לרשת. אם ה-UDF שלכם ניגש לשירותים אונליין, אתם צריכים ליצור את ה-UDF עם חיבור למשאב ב-Cloud. אם לא, הגישה של ה-UDF לרשת תיחסם עד שיגיע פסק זמן פנימי לחיבור.

בדוגמה הבאה אפשר לראות איך ניגשים לשירות Cloud Translation מפונקציית UDF ב-Python. בדוגמה הזו יש שני פרויקטים – פרויקט בשם my_query_project שבו יוצרים את פונקציית UDF ואת החיבור למשאב Cloud, ופרויקט שבו מפעילים את Cloud Translation בשם my_translate_project.

יצירת חיבור למשאב בענן

קודם יוצרים חיבור למשאב בענן ב-my_query_project. כדי ליצור את החיבור למשאב בענן, פועלים לפי השלבים בדף יצירת חיבור למשאב בענן.

אחרי שיוצרים את החיבור, פותחים אותו ובחלונית Connection info (פרטי החיבור), מעתיקים את מזהה חשבון השירות. תצטרכו את המזהה הזה כשמגדירים הרשאות לחיבור. כשיוצרים משאב חיבור, BigQuery יוצר חשבון שירות ייחודי למערכת ומשייך אותו לחיבור.

הענקת גישה לחשבון השירות של החיבור

כדי לתת לחשבון השירות של Cloud resource connection גישה לפרויקטים שלכם, צריך לתת לחשבון השירות את התפקיד Service usage consumer ‏(roles/serviceusage.serviceUsageConsumer) ב-my_query_project ואת התפקיד Cloud Translation API user ‏(roles/cloudtranslate.user) ב-my_translate_project.

  1. עוברים לדף IAM.

    כניסה לדף IAM

  2. מוודאים שהאפשרות my_query_project נבחרה.

  3. לוחצים על Grant Access.

  4. בשדה New principals, מזינים את מזהה חשבון השירות של חיבור משאב Cloud שהעתקתם קודם.

  5. בשדה Select a role (בחירת תפקיד), בוחרים באפשרות Service usage (שימוש בשירות) ואז באפשרות Service usage consumer (צרכן שימוש בשירות).

  6. לוחצים על Save.

  7. בוחרים פרויקט מתוך רשימת הפרויקטים.my_translate_project

  8. עוברים לדף IAM.

    כניסה לדף IAM

  9. לוחצים על Grant Access.

  10. בשדה New principals, מזינים את מזהה חשבון השירות של חיבור משאב Cloud שהעתקתם קודם.

  11. בשדה Select a role (בחירת תפקיד), בוחרים באפשרות Cloud translation (תרגום בענן) ואז בוחרים באפשרות Cloud Translation API user (משתמש ב-Cloud Translation API).

  12. לוחצים על Save.

יצירה של פונקציית UDF ב-Python שקוראת לשירות Cloud Translation

ב-my_query_project, יוצרים פונקציית UDF ב-Python שקוראת לשירות Cloud Translation באמצעות החיבור למשאב Cloud.

  1. עוברים לדף BigQuery.

    כניסה ל-BigQuery

  2. מזינים את הצהרת CREATE FUNCTION הבאה בעורך השאילתות:

    CREATE FUNCTION `PROJECT_ID.DATASET_ID`.translate_to_es(x STRING)
    RETURNS STRING LANGUAGE python
    WITH CONNECTION `PROJECT_ID.REGION.CONNECTION_ID`
    OPTIONS (entry_point='do_translate', runtime_version='python-3.11', packages=['google-cloud-translate>=3.11', 'google-api-core'])
    AS r"""
    
    from google.api_core.retry import Retry
    from google.cloud import translate
    
    project = "my_translate_project"
    translate_client = translate.TranslationServiceClient()
    
    def do_translate(x : str) -> str:
    
        response = translate_client.translate_text(
            request={
                "parent": f"projects/{project}/locations/us-central1",
                "contents": [x],
                "target_language_code": "es",
                "mime_type": "text/plain",
            },
            retry=Retry(),
        )
        return response.translations[0].translated_text
    
    """;
    
    -- Call the UDF.
    WITH text_table AS
      (SELECT "Hello" AS text
      UNION ALL
      SELECT "Good morning" AS text
      UNION ALL
      SELECT "Goodbye" AS text)
    SELECT text,
    `PROJECT_ID.DATASET_ID`.translate_to_es(text) AS translated_text
    FROM text_table;

    מחליפים את מה שכתוב בשדות הבאים:

    • PROJECT_ID.DATASET_ID: מזהה הפרויקט ומזהה מערך הנתונים
    • REGION.CONNECTION_ID: האזור של החיבור ומזהה החיבור
  3. לוחצים על  הפעלה.

    הפלט אמור להיראות כך:

    +--------------------------+-------------------------------+
    | text                     | translated_text               |
    +--------------------------+-------------------------------+
    | Hello                    | Hola                          |
    | Good morning             | Buen dia                      |
    | Goodbye                  | Adios                         |
    +--------------------------+-------------------------------+
    

מיקומים נתמכים

פונקציות UDF ב-Python נתמכות בכל המיקומים האזוריים והמיקומים שמכילים מספר אזורים ב-BigQuery.

תמחור

פונקציות UDF ב-Python מוצעות ללא חיובים נוספים.

כשהחיוב מופעל, התנאים הבאים חלים:

  • החיוב על פונקציות מוגדרות על ידי המשתמש ב-Python מתבצע באמצעות מק''ט שירותי BigQuery.
  • החיובים הם יחסיים לכמות המחשוב והזיכרון שנצרכו כשמפעילים את פונקציית ה-UDF של Python.
  • לקוחות שמשתמשים ב-UDF של Python מחויבים גם בעלות של יצירה או יצירה מחדש של קובץ האימג' של קונטיינר ה-UDF. החיוב הזה הוא יחסי למשאבים שנעשה בהם שימוש כדי ליצור את קובץ האימג' עם קוד הלקוח והתלות.
  • אם פונקציות UDF של Python גורמות לתעבורת נתונים יוצאת (egress) ברשת חיצונית או באינטרנט, יופיע גם חיוב על תעבורת נתונים יוצאת באינטרנט במסגרת מסלול הפרימיום מ-Cloud Networking.