Python y Rust ocupan extremos aparentemente opuestos del espectro del lenguaje. Pitóninterpretado en tiempo de ejecución, ofrece a los desarrolladores un entorno de programación flexible y cómodo, pero a costa de la velocidad bruta. Óxido proporciona velocidad y garantías de seguridad de la memoria, pero requiere que aprenda un nuevo paradigma para manejar las operaciones de la memoria.
En teoría, estos idiomas no deberían competir; deberían cooperar. Y en la práctica, pueden hacerlo. Rust puede beneficiarse de la facilidad de uso de Python y Python puede beneficiarse de la velocidad y seguridad de Rust.
Si desea utilizar Rust con Python o Python con Rust, deberá tener al menos cierta familiaridad con ambos lenguajes para obtener los mejores resultados. También deberás decidir cuál de los dos es tu idioma principal, ya que las opciones para cada enfoque son significativamente diferentes.
Llamar a Rust desde Python con PyO3
Si Python es su lenguaje principal, la integración con Rust funciona conceptualmente de la misma manera que la integración de Python con C. La implementación predeterminada de Python, escrita en C, usa extensiones escritas en C o usando una ABI compatible con C. Las extensiones escritas en Rust que usan la misma ABI también funcionarán, aunque eso no es automático; debe usar cajas diseñadas para proporcionar enlaces para funciones de Rust a la API de Python C.
Creando enlaces de Rust en Python
El proyecto más reconocido para crear enlaces de Rust en Python es PyO3. Se puede utilizar para escribir módulos de Python en Rust o para incrustar el tiempo de ejecución de Python en un binario de Rust.
PyO3 potencia otro proyecto, Maturín, que es una herramienta para crear cajas Rust con empaques y enlaces de Python. Cuando se instala en un Entorno virtual de Python, Maturin se puede utilizar desde la línea de comandos para inicializar un nuevo proyecto de Rust con enlaces de Python habilitados. El desarrollador usa directivas en el código Rust para indicar qué funciones de Rust exponer a Python y cómo exponer todo el proyecto de Rust a Python como un módulo importable.
Mapeo de tipos de Rust y Python
Uno de los aspectos útiles del PyO3 es su asignaciones entre tipos Rust y Python. Las funciones escritas en Rust pueden aceptar tipos nativos de Python o tipos de Rust convertidos a partir de tipos de Python. Por ejemplo, un bytearray
o bytes
objeto en Python se asigna elegantemente a un Vec<u8>
en Rust, y un str
en Python se puede representar como Rust String
.
Tipos más complejos, como un diccionario de pitón o un número entero que es demasiado grande para un número entero nativo de la máquina, también tienen conversiones de Rust, pero algunas requieren componentes opcionales. Por ejemplo, si desea utilizar números enteros de Python de tamaño arbitrario, instalaría el num-bigint
característica opcional en PyO3, y tener esos números enteros expresados en Rust como num_bigint::BigInt
o num_bigint::BigUint
tipos.
La conversión de Python a Rust genera un costo por llamada, pero le libera de tener que usar tipos de Python por completo en el código de Rust. En el cito En todo el mundo, esto es similar a las conversiones a tipos C: hay un costo por cada conversión, pero conllevan importantes aceleraciones si su objetivo es el procesamiento numérico completamente en C.
Llamar a Python desde Rust
Si eres principalmente un desarrollador de Rust pero quieres usar Python dentro de una aplicación de Rust, PyO3 también tiene mecanismos para llamar a Python desde el código Rust.
El código Python se puede definir en línea en un programa Rust, compilarse en código de bytes de Python y ejecutarse mediante llamadas de Rust. Estructuras de óxido como HashMap
o BTreeMap
se puede utilizar para pasar listas de argumentos posicionales o de palabras clave. Incluso puedes evaluar expresiones individuales si eso es todo lo que necesitas.
Los programas de Rust pueden invocar el intérprete CPython y trabajar con él, lo que le permite crear y manipular objetos Python en Rust y realizar llamadas a bibliotecas. Los archivos de código Python existentes también se pueden cargar y utilizar, pero es un riesgo potencial para la seguridad, así que no cargue código que no sea de confianza ni utilice esta opción en una situación en la que pueda hacerlo.
Si está más familiarizado con Rust que con Python, es una buena idea tener al menos cierta familiaridad con el API de Python C y los diversos tipos de objetos de Python antes de sumergirse.
Un proyecto anterior, el caja de Pythontambién permitió Python dentro de una aplicación Rust, pero ya no se mantiene activamente y sus desarrolladores recomiendan usar PyO3 en su lugar.
Consejo de rendimiento
Una advertencia importante con PyO3 es minimizar siempre la cantidad de veces que los datos pasan de un lado a otro entre los dos lenguajes. Cada llamada de Python a Rust o viceversa genera algunos gastos generales. Si los gastos generales superan el trabajo que realiza en Rust, no verá ninguna mejora significativa en el rendimiento.
Como ejemplo, si está realizando un bucle sobre una colección de objetos, envíe el objeto a Rust y realice el bucle allí. Esto es más eficiente que realizar un bucle en el lado de Python y llamar al código Rust con cada iteración del bucle.
Esta directriz también se aplica en general a las integraciones entre Python y otro código que utiliza la ABI de Python C, como los módulos Cython.
Copyright © 2024 IDG Communications, Inc.