Ejemplo: Importación de módulos personalizados desde la biblioteca de Python
Define las funciones escalares con sintaxis del lenguaje Python. Puede utilizar los módulos de la biblioteca estándar de Python y los módulos preinstalados de Amazon Redshift. También puede crear sus propios módulos personalizados de la biblioteca de Python e importar las bibliotecas a sus clústeres, o utilizar las bibliotecas existentes de Python o terceros.
No puede crear una biblioteca que contenga un módulo con el mismo nombre que un módulo de la biblioteca estándar de Python o un módulo de Python preinstalado de Amazon Redshift. Si una biblioteca existente instalada por el usuario usa el mismo paquete de Python que la biblioteca que creó, debe eliminar la biblioteca existente antes de instalar la nueva biblioteca.
Para instalar bibliotecas personalizadas debe ser un super usuario o tener el privilegio USAGE ON LANGUAGE plpythonu
; no obstante, cualquier usuario con privilegios suficientes como para crear funciones puede usar las bibliotecas instaladas. Puede consultar el catálogo del sistema PG_LIBRARY para obtener información acerca de las bibliotecas instaladas en su clúster.
Importación de un módulo personalizado de Python al clúster
En la presente sección, se ofrece un ejemplo de importación de un módulo personalizado de Python a su clúster. Para llevar a cabo los pasos de esta sección, debe tener un bucket de Amazon S3 donde cargar el paquete de la biblioteca. Luego instalará el paquete en su clúster. Para obtener más información acerca de la creación de buckets, consulte Creación de un bucket en la Guía del usuario de Amazon Simple Storage Service.
En este ejemplo, supongamos que crea una UDF para trabajar con posiciones y distancias en sus datos. Conéctese a su clúster de Amazon Redshift desde una herramienta cliente SQL y ejecute los siguientes comandos para crear las funciones.
CREATE FUNCTION f_distance (x1 float, y1 float, x2 float, y2 float) RETURNS float IMMUTABLE as $$ def distance(x1, y1, x2, y2): import math return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) return distance(x1, y1, x2, y2) $$ LANGUAGE plpythonu; CREATE FUNCTION f_within_range (x1 float, y1 float, x2 float, y2 float) RETURNS bool IMMUTABLE as $$ def distance(x1, y1, x2, y2): import math return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) return distance(x1, y1, x2, y2) < 20 $$ LANGUAGE plpythonu;
Tenga en cuenta que algunas líneas de código se duplican en las funciones previas. Esa duplicación es necesaria porque una UDF no puede hacer referencia al contenido de otra UDF y ambas funciones requieren la misma funcionalidad. No obstante, en lugar de duplicar el código en varias funciones, puede crear una biblioteca personalizada y configurar las funciones para que la usen.
Para ello, en primer lugar cree el paquete de biblioteca siguiendo los pasos a continuación:
-
Cree una carpeta con el nombre geometry. Esa carpeta es el paquete de nivel superior de la biblioteca.
-
En la carpeta geometry, cree un archivo llamado
__init__.py
. Tenga en cuenta que el nombre del archivo tiene dos caracteres de guión bajo doble. Este archivo le indica a Python que el paquete puede inicializarse. -
En la carpeta geometry, cree también una carpeta llamada trig. Esa carpeta es el subpaquete de la biblioteca.
-
En la carpeta trig, cree otro archivo llamado
__init__.py
y un archivo llamadoline.py
. En esta carpeta,__init__.py
le indica a Python que el subpaquete puede inicializarse y queline.py
es el archivo que tiene el código de biblioteca.La estructura de carpetas y archivos debe ser igual a la siguiente:
geometry/ __init__.py trig/ __init__.py line.py
Para obtener más información acerca de la estructura del paquete, visite Modules
en el tutorial de Python que se encuentra en el sitio web de Python. -
El siguiente código tiene una clase y las funciones de miembro de la biblioteca. Cópielo y péguelo en
line.py
.class LineSegment: def __init__(self, x1, y1, x2, y2): self.x1 = x1 self.y1 = y1 self.x2 = x2 self.y2 = y2 def angle(self): import math return math.atan2(self.y2 - self.y1, self.x2 - self.x1) def distance(self): import math return math.sqrt((self.y2 - self.y1) ** 2 + (self.x2 - self.x1) ** 2)
Una vez que haya creado el paquete, haga lo siguiente para prepararlo y cargarlo en Amazon S3.
-
Comprima el contenido de la carpeta geometry en un archivo .zip con el nombre geometry.zip. No incluya la carpeta geometry en sí; incluya solamente el contenido de la carpeta, tal y como se muestra a continuación:
geometry.zip __init__.py trig/ __init__.py line.py
-
Cargue geometry.zip en el bucket de Amazon S3.
importante
Si el bucket de Amazon S3 no se encuentra en la misma región que el clúster de Amazon Redshift, debe utilizar la opción REGION para especificar la región en la que se encuentran los datos. Para obtener más información, consulte CREATE LIBRARY.
-
Desde su herramienta cliente SQL, ejecute el siguiente comando para instalar la biblioteca. Reemplace
<bucket_name>
con el nombre del bucket y reemplace<access key id>
y<secret key>
con una clave de acceso y una clave de acceso secreta de las credenciales de usuario de AWS Identity and Access Management (IAM).CREATE LIBRARY geometry LANGUAGE plpythonu FROM 's3://
<bucket_name>
/geometry.zip' CREDENTIALS 'aws_access_key_id=<access key id>
;aws_secret_access_key=<secret key>
';
Después de instalar la biblioteca en su clúster, debe configurar sus funciones para poder usarla. Para ello, ejecute los siguientes comandos.
CREATE OR REPLACE FUNCTION f_distance (x1 float, y1 float, x2 float, y2 float) RETURNS float IMMUTABLE as $$ from trig.line import LineSegment return LineSegment(x1, y1, x2, y2).distance() $$ LANGUAGE plpythonu; CREATE OR REPLACE FUNCTION f_within_range (x1 float, y1 float, x2 float, y2 float) RETURNS bool IMMUTABLE as $$ from trig.line import LineSegment return LineSegment(x1, y1, x2, y2).distance() < 20 $$ LANGUAGE plpythonu;
En los comandos anteriores, import trig/line
elimina el código duplicado de las funciones originales presentadas en esta sección. Puede reusar la funcionalidad brindada por esta biblioteca en distintas UDF. Tenga en cuenta que para importar el módulo, solamente necesita especificar la ruta del subpaquete y el nombre del módulo (trig/line
).