Altova MapForce 2027 Professional Edition

En este tema se explica cómo importar un módulo de Python a MapForce. Un módulo de Python es un archivo de Python (.py) que contiene código de Python, como funciones, clases y variables.

 

Las funciones, clases y valores de Python definidos en el módulo pueden aparecer en la ventana Bibliotecas si cumplen los requisitos descritos en este tema. Las funciones de Python pueden utilizarse, por tanto, en una asignación como cualquier otra función de MapForce.

 

Nota: Debe tener instalado Python 3.6 o una versión posterior en su ordenador. La plataforma de MapForce (32 bits, 64 bits) debe coincidir con la de Python.

 

Nota importante

 

•Para importar y ejecutar funciones de Python se requieren las ediciones MapForce Professional y Enterprise.

•Las funciones de Python se ejecutan mediante el lenguaje de transformación integrado Built-In. No están disponibles en el código generado en Java, C#, C++ o XSLT.

•MapForce utiliza la instalación de Python configurada en Herramientas | Opciones | Python. Si no se ha especificado ninguna ruta en el cuadro de diálogo Opciones, MapForce intentará detectar una instalación de Python mediante las variables de entorno PYTHONHOME y PATH.

•Solo se importan aquellos miembros cuyos parámetros y valores devueltos estén anotados con un tipo compatible (ver tipos compatibles más abajo). No se importan los siguientes miembros:

 

oMiembros cuyos nombres comienzan con un guión bajo

oMiembros heredados de una clase definida fuera del módulo

 

•Si el archivo .py sufre algún cambio, MapForce se lo notifica y le permite volver a cargarlo. Al recargar el módulo, se vuelven a importar todas las funciones.

 

Automatización con MapForce Server

Cuando use MapForce Server para ejecutar una asignación que contenga funciones Python personales, es posible que tenga que especificar la ruta de acceso al directorio principal de Python. Para obtener más información, consulte la descripción del comando run en la documentación de MapForce Server (https://www.altova.com/es/documentation#mapforceserver).

 

Automatización con FlowForce Server

Cuando use FlowForce Server para ejecutar una asignación que contenga funciones Python personales, es posible que tenga que configurar el entorno de Python en el archivo .tool y garantizar que el módulo de Python esté disponible en el equipo en el que se ejecuta FlowForce Server. Para obtener más información, consulte el tema Archivos tool en la documentación de FlowForce Server (https://www.altova.com/es/documentation#flowforceserver).

 

Archivos de ejemplo

A efectos de prueba, puede utilizar un ejemplo disponible en MapForceExamples\Python\FormatNumber.mfd, que llama a la función definida en Python\Format\Format.py.

 

Los ejemplos que se utilizan en este tema proceden del archivo MapForceExamples\Python\Sales\Sales.py.

 

Importación de módulos Python

Para añadir un módulo Python como biblioteca de MapForce, siga estos pasos:

 

1.Haga clic en el botón Agregar o quitar bibliotecas, en la parte inferior de la ventana Bibliotecas. Se abre la ventana Gestionar bibliotecas.

2.Para importar funciones como biblioteca local (solo en el ámbito del documento actual), haga clic en Agregar debajo del nombre de la asignación actual. Para importar funciones como biblioteca global (a nivel de programa), haga clic en Agregar junto a Bibliotecas globales importadas.

3.Busque el archivo .py que desee importar; por ejemplo, MapForceExamples\Python\Sales\Sales.py. La biblioteca importada ya aparece en la ventana Bibliotecas. También puede hacer doble clic en un archivo .py en la ventana Proyecto para añadirlo como biblioteca.

 

Si no ve la biblioteca que acaba de importar en la ventana Bibliotecas, asegúrese de que el lenguaje de transformación es Built-In. Para añadir una función a la asignación, arrástrela desde la ventana Bibliotecas hasta el área de asignación.

 

Tipos Python compatibles

La tabla siguiente muestra la correspondencia entre los tipos XML y los tipos Python compatibles:

 

Tipo Schema

Tipo Python

xs:string

str

xs:integer

int

xs:double

float

xs:boolean

bool

xs:decimal

decimal.Decimal

xs:base64Binary

bytes

 

MapForce permite pasar valores de XML Schema a Python y de Python a XML Schema, utilizando los tipos correspondientes de la tabla. Los tipos Python pueden utilizarse para parámetros, valores devueltos y atributos de módulos o clases. Además, MapForce admite clases definidas en el mismo módulo, siempre que MapForce pueda utilizarlas (véase más adelante Objetos).

 

Las funciones y los métodos deben incluir anotaciones de tipo para sus parámetros y valores devueltos (por ejemplo, a: int o -> int). Si un parámetro o un valor devuelto no está anotado o tiene un tipo no compatible, no se importará la función o el método correspondiente.

 

Tipos Python incompatibles

El resto de tipos Python, como los que se enumeran a continuación, no son compatibles:

 

•Clases y tipos importados distintos de decimal.Decimal

•list, dict, tuple, set y otros tipos de contenedor

•Tipos genéricos como list[int]

•Optional[T] y Union[...]

•Uniones PEP 604, como int | str

•Iteradores y generadores

•Funciones y generadores asíncronos

•Listas de argumentos de longitud variable (*args, **kwargs)

 

Objetos

MapForce admite objetos que sean instancias de clases utilizables definidas en el módulo importado. MapForce puede obtener dicha instancia a través de un constructor, un valor a nivel de módulo o una función de fábrica, y, a continuación, puede pasar la instancia a funciones o utilizarla para llamar a métodos de instancia y leer propiedades de instancia.

 

El fragmento de código que figura a continuación muestra la clase CurrencyFormatter definida en el archivo Sales.py..

 

class CurrencyFormatter:

   DEFAULT_PATTERN: str = ",.2f"

 

   def __init__(self, prefix: str, pattern: str):

       self._prefix = prefix

       self._pattern = pattern

 

   @property

   def prefix(self) -> str:

       return self._prefix

 

   def format_amount(self, amount: Decimal) -> str:

       return self._prefix + format(amount, self._pattern)

 

   @staticmethod

   def plain(amount: Decimal) -> str:

       return format(amount, CurrencyFormatter.DEFAULT_PATTERN)

 

Esta clase añade cinco elementos a la ventana Bibliotecas:

 

•CurrencyFormatter(): El constructor que crea una nueva instancia de CurrencyFormatter.

•CurrencyFormatter.DEFAULT_PATTERN: Un atributo de clase que se puede leer sin necesidad de una instancia.

•CurrencyFormatter.format_amount: Un método de instancia que opera sobre una instancia de CurrencyFormatter.

•CurrencyFormatter.prefix: Una propiedad que puede leerse desde una instancia de CurrencyFormatter.

•CurrencyFormatter.plain: Un método estático al que se puede llamar sin una instancia. Los métodos de clase se importan de la misma manera.

 

Obtener y pasar instancias

MapForce puede obtener una instancia de una clase utilizable llamando a su constructor o a través de otro miembro utilizable que devuelva una instancia. Por ejemplo, una instancia puede ser proporcionada por un valor a nivel de módulo o por una función de fábrica:

 

EURO: CurrencyFormatter = CurrencyFormatter("EUR ", CurrencyFormatter.DEFAULT_PATTERN)

 

 

def formatter_for(prefix: str) -> CurrencyFormatter:

   return CurrencyFormatter(prefix, CurrencyFormatter.DEFAULT_PATTERN)

 

 

def format_with(formatter: CurrencyFormatter, amount: Decimal) -> str:

   return formatter.format_amount(amount)

 

En el fragmento de código anterior, EURO es un valor a nivel de módulo que contiene una instancia de CurrencyFormatter, y formatter_for() es una función de fábrica que devuelve una instancia de CurrencyFormatter. La función format_with() acepta una instancia de CurrencyFormatter como parámetro.

 

Objetos invocables

Un valor que contiene una instancia de una clase que define el método __call__ puede invocarse como si fuera una función (ver fragmento de código siguiente). Por lo tanto, MapForce importa dicho valor como una función y añade () a su nombre en la ventana Bibliotecas. En el ejemplo que figura a continuación, ROUND_CENTS es un valor que puede invocarse como si fuera una función. MapForce lo importa como ROUND_CENTS() en la ventana Bibliotecas.

 

class Rounder:

   def __init__(self, places: int):

       self._places = places

 

   def __call__(self, amount: Decimal) -> Decimal:

       return round(amount, self._places)

 

 

ROUND_CENTS: Rounder = Rounder(2)

 

Funciones y valores

Una función a nivel de módulo se importa como una función. Un valor a nivel de módulo se importa como una función sin parámetros que devuelve dicho valor.

 

El fragmento de código que figura a continuación muestra la definición de los valores a nivel de módulo (VAT_RATE y REPORT_TITLE) y de las funciones a nivel de módulo (net_amount y period).

 

VAT_RATE: Decimal = Decimal("0.20")

REPORT_TITLE: str = "Regional sales"

 

 

def net_amount(gross: Decimal) -> Decimal:

   """Removes VAT from a gross amount."""

   return gross / (1 + VAT_RATE)

 

 

def period(start: str, end: str) -> str:

   return start + " - " + end

 

El módulo también contiene una función decorada con @functools.lru_cache. MapForce importa dichas funciones como de costumbre y utiliza los parámetros y el tipo devuelto de la función original para determinar su interfaz. El decorador no modifica los parámetros ni el tipo devuelto que MapForce indica para la función.

 

@functools.lru_cache(maxsize=None)
def region_name(code: str) -> str:
    """Amplía un código de región. La tabla de búsqueda se crea únicamente la primera vez que se utiliza."""
    return _region_names().get(code, code)

 

Reutilización de objetos y almacenamiento en caché

Cuando se utiliza una función o un constructor en una asignación, MapForce lo invoca para cada fila que pasa por ella. Si un constructor crea un objeto cuya inicialización lleva mucho tiempo, crear una nueva instancia para cada fila puede resultar ineficaz.

 

Para reutilizar el mismo objeto, créelo una sola vez a nivel de módulo y conecte ese valor allí donde se necesite la instancia:

 

EURO: CurrencyFormatter = CurrencyFormatter("EUR ", CurrencyFormatter.DEFAULT_PATTERN)

 

Al conectar EURO al primer parámetro CurrencyFormatter.format_amount, el objeto se crea una sola vez, al cargarse el módulo, y se reutiliza para cada fila. Los valores a nivel de módulo se leen en tiempo real cada vez que se utilizan. Por lo tanto, si el código de Python actualiza un valor a nivel de módulo, MapForce lee el valor actualizado la siguiente vez que se utilice.

 

También puede almacenar en caché los resultados de las llamadas a funciones que consumen muchos recursos. Un diccionario a nivel de módulo o @functools.lru_cache almacena los resultados devueltos anteriormente:

 

@functools.lru_cache(maxsize=None)

def region_name(code: str) -> str:

   """Amplía un código de región. La tabla de búsqueda se crea únicamente la primera vez que se utiliza."""

   return _region_names().get(code, code)

 

El decorador @functools.lru_cache hace que la función region_name() se ejecute una vez por cada código de región distinto. Si las filas siguientes utilizan un código que ya se ha procesado, la función almacenada en caché devuelve el resultado almacenado en caché en lugar de volver a ejecutar la función.

 

Las funciones y otros nombres que comienzan con un guión bajo, como _region_names, se consideran privados del módulo y MapForce no los importa.

 

Tenga en cuenta los siguientes aspectos:

 

•Los objetos a nivel de módulo y los valores almacenados en caché siguen estando disponibles mientras dure la asignación. Se reinician cuando se vuelve a importar la biblioteca.

•MapForce evalúa una asignación por subprocesos simples, por lo que no es necesario bloquear la caché a nivel de módulo.

•Evite utilizar @functools.lru_cache en un método de instancia cuando se cree una nueva instancia para cada fila. En este caso, la caché está asociada a las instancias y puede seguir creciendo. Utilice, en su lugar, una función a nivel de módulo para el almacenamiento en caché.

•MapForce puede leer los atributos a nivel de módulo y de clase, pero no puede asignarles valores. Utilice código Python para actualizar estos valores.

 

© 2020-2026 Altova GmbH