Chaquopy: uso de Python en aplicaciones de Android | de Shubham Panchal | marzo 2023

Contenidos

Use scripts y paquetes de Python para optimizar las aplicaciones de Android

Python es uno de los lenguajes más populares en la comunidad de desarrolladores debido a su simplicidad, robustez y un gran ecosistema de paquetes que lo hacen extremadamente útil en múltiples dominios. El uso de paquetes como NumPy y SciPy permite a los programadores realizar operaciones matemáticas de alto nivel que de otro modo no estarían disponibles en otros lenguajes de programación. ¿Qué tal llevar el poder de Python a las aplicaciones de Android? Chaquopy es un marco que puede ayudar a los desarrolladores a ejecutar scripts de Python desde código Java/Kotlin en aplicaciones de Android. A diferencia de otras bibliotecas multilingües, no hay problemas con el NDK o el código nativo, y la instalación es sencilla. En esta historia, exploraremos Chaquopy, su arquitectura y cómo usarlo con el código Kotlin. Así como funcionan la mayoría de las interfaces entre idiomas, Python y Android comparten un origen común de C/C++, que les permite comunicarse a través de un medio común. El NDK de Android permite a los desarrolladores usar bibliotecas nativas (escritas en C/C++) dentro de una aplicación de Android, lo cual es ideal para gráficos de alto rendimiento y computación científica. Chaquopy usa CPython, una implementación de Python escrita en lenguaje C. Contrariamente a la idea errónea popular, Python no es un lenguaje puramente interpretado. El código fuente de Python se compila primero en un código de bytes especial, que luego CPython interpreta. CPython es solo una de varias implementaciones de Python, otras incluyen PyPy, IronPython, Jython, etc.Arquitectura Chaquopy. Fuente: Malcolm Smith (con permisos adquiridos) El equipo de Chaquopy construye CPython utilizando la cadena de herramientas NDK de Android. CPython se descarga del repositorio Maven Central mediante el complemento Gradle de Chaquopy mientras se construye el proyecto, y los usuarios no necesitan descargar NDK para el proceso. También descarga los tiempos de ejecución de Chaquopy que conectan el código Java/Kotlin a Python a través de JNI. Mientras tanto, también necesitamos el administrador de paquetes pip de Python, que puede descargar paquetes para el intérprete. Paquetes populares como NumPy y SciPy usan código nativo para realizar cálculos intensivos de CPU que deben construirse antes de la instalación. Por lo tanto, el equipo de Chaquopy mantiene sus propios repositorios de paquetes nativos diseñados específicamente para la arquitectura ARM de Android. Los mantenedores de estos paquetes no crean código nativo para los objetivos de Android debido a que la base de usuarios es más pequeña, por lo que el equipo de Chaquopy los crea para los objetivos de Android y los distribuye a través de su propio repositorio. Los paquetes de Python puro no requieren compilación externa y el intérprete de Chaquopy puede ejecutarlos directamente. Para una descripción general, Chaquopy contiene tres componentes principales:

  1. Complemento Chaquopy Gradle
  2. Tiempo de ejecución de Chaquopy
  3. repositorio de paquetes

1.1. Dependencias de Gradle y especificaciones ABI

Para agregar Chaquopy a su proyecto de Android nuevo/existente, vaya a la secuencia de comandos build.gradle a nivel de proyecto, donde definimos los complementos de Gradle para el proyecto, y agregue el complemento Gradle de Chaquopy, complementos {id ‘com.android .application’ versión ‘7.3 .0’ aplicar la identificación incorrecta ‘com.android.library’ versión ‘7.3.0’ aplicar la identificación incorrecta ‘org.jetbrains.kotlin.android’ versión ‘1.7.21’ aplicar la identificación incorrecta ‘com.chaquo.python” versión “13.0 .0” apply false } A continuación, en build.gradle, a nivel de módulo, agregamos el complemento Chaquopy y también especificamos los filtros ABI, complementos {id ‘com.android.application’id ‘org.jetbrains .kotlin.android’ id ‘com.chaquo.python’}android {…defaultConfig {…ndk {abiFilters «armeabi-v7a» //, «arm64-v8a», «x86», «x86_64»}} …}Como mencionado en los documentos oficiales, el intérprete de Python es un componente nativo creado con el NDK de Android. El NDK crea código nativo para arquitecturas específicas como arm, x86 o x86_64. Diferentes dispositivos admiten diferentes arquitecturas, por lo que solo podemos incluir esa compilación específica del intérprete de Python en lugar de compilar para todas las arquitecturas, lo que aumenta el tamaño de la aplicación. Los documentos oficiales de Android dicen:

El comportamiento predeterminado del sistema de compilación es envolver los archivos binarios para cada ABI en un solo APK, también conocido como APK gordo. Un APK gordo es significativamente más grande que uno que solo contiene los archivos binarios para una sola ABI. La compensación es una compatibilidad más amplia, pero a costa de un APK más grande. Se recomienda encarecidamente usar paquetes de aplicaciones o divisiones de APK para reducir el tamaño de sus APK y mantener la máxima compatibilidad con dispositivos.

1.2. Versión de Python y paquetes PIP

A continuación, configuramos la versión de Python que debe construirse. Podemos especificar esto cambiando build.gradle ,plugins {id ‘com.android.application’id ‘org.jetbrains.kotlin.android’id ‘com.chaquo.python’}android {…defaultConfig { en el nivel del módulo . …ndk {abiFilters «armeabi-v7a» //, «arm64-v8a», «x86», «x86_64»}python {version «3.8»}}…}Diferentes versiones de Chaquopy admiten diferentes versiones de Python con diferentes mínimos requisitos a nivel API. Utilice esta tabla para encontrar una versión que satisfaga sus necesidades. A continuación especificamos los paquetes a instalar en el intérprete de Python. Un nombre de archivo sdist o rueda, relativo al directorio del proyecto: install «MyPackage-1.2.3-py2.py3-none-any.whl»// Un directorio que contiene un archivo setup.py, relativo al directorio del proyecto// (debe contener al menos una barra inclinada): instale «./MyPackage»// «-r»` seguido de un nombre de archivo de requisitos, relativo al // directorio del proyecto: instale «-r», «requirements.txt»}}}Hay varios formas de poner paquetes en la instalación de Chaquopy; Puede ser un nombre de paquete con una versión específica, un paquete personalizado o una lista de paquetes de Requisitos.txt. En Python, usamos funciones o miembros de datos que pertenecen a un módulo de Python, que es un archivo .py que contiene el código fuente. Para usar cualquier miembro de un módulo de Python, primero debe encontrar el código fuente de Python en el /app/src/main/python. # Contenido de my_module.pyimportar numpy como npdef get_exec_details():return __file__def sumOp (nums):return sum(nums)def powOp( a , x ):return a**xdef npMatrixSum( m , n ):mat = np.ones ( ( m , n ) )mat_sum = np.sum( mat , axis =1 )return mat_sumclass Operations:num_ops = 2def meanOp( self , nums ):return sum( nums ) / len( nums )def maxOp( self , nums ) :return max(nums)nums_len = 10nums_len_str = «diez»ops = operaciones ()Ubicación del módulo de Python en relación con el proyecto de Android y su contenido. Fuente de la imagen: imagen del autor Para usar miembros de my_module usamos el método Python.getModule pasando el nombre del módulo. Antes de eso, debemos habilitar Python para la aplicación, que se refleja en el método onCreate de la aplicación, la clase App: Application() {override fun onCreate() {super.onCreate()if( !Python.isStarted() ) { Python.start( Agregar AndroidPlatform(this))}}}Aplicación a AndroidManifest.xml, Y luego, en MainActivity, podemos llamar a Python.getInstance (de lo contrario, obtendríamos una PyException), val py = Python.getInstance() val module = py.getModule («my_module»)

2.1. Acceso a variables (miembros de datos)

Para usar un elemento de datos como nums_len en my_module.py, val numsLength = module[ «nums_len» ]?.toInt()println( «La longitud de Nums es $numsLength» )La longitud de Nums es 10 Para acceder a los atributos de las operaciones de objetos de la clase Operations, val ops = module[ «ops» ]!!println( «Operaciones: $ops» )println( «Número_ops : ${ ops[ «num_ops» ] }» )println( «función intermedia: ${ operaciones[ «meanOp» ] }» ) operaciones: num_ops: 2 función media: >

2.2. llamando a funciones

Debido a que una función es un objeto en Python, se permite acceder a las funciones como valores del módulo. Luego usamos el método PyObject.call para pasar argumentos a una función y recuperar los resultados (si la función devuelve un valor) val sumFunc = módulo[ «sumOp» ]val sum = sumFunc?.call( intArrayOf( 12 , 25 , 32 ) )val powFun = módulo[ «powOp» ]val pow = powFun?.call( 5 , 2 )println( «Sum: $sum» )println( «Pow: $pow» )Sum: 69Pow: 25Para acceder a funciones miembro desde el objeto ops, val meanFunc = ops[ «meanOp» ]val mean = meanFunc?.call( intArrayOf( 23 , 45 , 12 , 91 ) )println( «Mean: $mean» )// ORval mean = ops.callAttr( «meanOp» , intArrayOf( 23 , 45 , 12 , 91 ) devuelve = np.ones( ( m , n ) )mat_sum = np.sum( mat , axis=1 )return mat_sumval npSumFunc = módulo[ «npMatrixSum» ]val salida = npSumFunc?.call( 2 , 3 )// ORval salida = module.callAttr( «npMatrixSum» , 2 , 3 )println( «Salida: $salida» )println( «Forma de salida: ${salida!![ «shape» ] }»)Salida: [3. 3.]Formulario de salida: (2,) ¡Espero haber agregado una nueva herramienta a su caja de herramientas de desarrollo de Android! Chaquopy es una gran herramienta con una sintaxis ordenada y una instalación sencilla. Asegúrate de usarlo en tu próximo proyecto de Android. ¡Sigue aprendiendo y que tengas un buen día!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.