Étudiez l'échange de données Java et Python avec Apache Arrow

Cette fois, j'ai utilisé Apache Arrow pour étudier l'échange de données entre Java et python.

introduction

On s'attend à ce que l'échange de données à l'aide d'Apache Arrow puisse être copié entre les systèmes et les langues sans copie en mémoire. Pour écrire la conclusion en premier, dans cette recherche, elle a été échangée via un tableau d'octets au format Apache Arrow. Vous n'êtes pas obligé de l'écrire sur votre disque local, mais la sérialisation Java et la désérialisation python entraîneront une copie des données en mémoire. Je pense que l'avantage de la méthode introduite cette fois-ci est qu'il est facile de faire le lien entre les langues car il existe un format commun à haute vitesse appelé Apache Arrow.

À propos de l'échange de données Java et Python avec Apache Arrow

Apache Arrow avait une bibliothèque appelée jvm pour échanger des données entre Java et python. Cette bibliothèque implémente une fonction qui, si vous passez un objet Java Apache Arrow VectorSchemaRoot, le convertira en un RecordBatch python.

def record_batch(jvm_vector_schema_root):
    """
    Construct a (Python) RecordBatch from a JVM VectorSchemaRoot
    Parameters
    ----------
    jvm_vector_schema_root : org.apache.arrow.vector.VectorSchemaRoot
    Returns
    -------
    record_batch: pyarrow.RecordBatch
    """

Par conséquent, on suppose que l'échange de données entre Java et python peut être facilement effectué en utilisant py4j. image.png

Préparation préalable

Obtenez les pots dont vous avez besoin pour utiliser py4j. Le pom suivant apporte la flèche et les bocaux py4j localement.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>gtest</groupId>
  <artifactId>gtest</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>gtest</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.apache.arrow</groupId>
      <artifactId>arrow-vector</artifactId>
      <version>0.12.0</version>
    </dependency>
    <dependency>
      <groupId>net.sf.py4j</groupId>
      <artifactId>py4j</artifactId>
      <version>0.10.8.1</version>
    </dependency>
  </dependencies>

</project>

La commande maven est la suivante.

$ mvn dependency:copy-dependencies -DoutputDirectory=./lib -f ./pom.xml

Essayez la bibliothèque jvm

Créez une classe Java simple en vous référant à l'exemple py4j. Il implémente également une fonction qui renvoie VecotrSchemaRoot pour validation sur py4j.

import java.util.List;
import java.util.ArrayList;

import py4j.GatewayServer;

import org.apache.arrow.memory.RootAllocator;
import org.apache.arrow.vector.BitVector;
import org.apache.arrow.vector.VectorSchemaRoot;

public class Py4jExample {

  public static void main( final String[] args ) {
    Py4jExample app = new Py4jExample();
    GatewayServer server = new GatewayServer( app );
    server.start();
  }

  /**
   *Préparez une fonction pour créer un VectorSchemaRoot à essayer.
   */
  public static VectorSchemaRoot create() {
    RootAllocator allocator = new RootAllocator( Integer.MAX_VALUE );
    BitVector vector = new BitVector( "test" , allocator );
    vector.allocateNew( 1 );
    vector.setSafe( 0 , 1 );
    vector.setValueCount( 1 );

    List list = new ArrayList();
    list.add( vector );

    VectorSchemaRoot root = new VectorSchemaRoot( list );
    root.setRowCount( 1 );

    return root;
  }

}

Compilez et démarrez.

$ javac -cp lib/*:. Py4jExample.java
$ java -cp lib/*:. Py4jExample &

Maintenant que nous sommes prêts à appeler depuis python, écrivons le processus python.

from py4j.java_gateway import JavaGateway
import pyarrow as pa
import pyarrow.jvm as j
from pyarrow import RecordBatch

gateway = JavaGateway()

root = gateway.jvm.Py4jExample.create()
rb = j.record_batch( root )

df = rb.to_pandas()

J'ai pensé qu'il serait facile de convertir de java en record_batch de python en utilisant la bibliothèque jvm comme celle-ci ...

$ python test.py
Segmentation fault

Vous pouvez l'exécuter jusqu'au point où vous obtenez RecordBatch, mais il semble se bloquer lorsque vous appelez to_pandas (). Je ne peux pas dire si mon environnement était mauvais, mais je ne semblais pas le comprendre tout de suite, alors j'ai décidé d'abandonner cette fois.

Échange de données dans un tableau d'octets d'Apache Arrow

Alternativement, Apache Arrow implémente également un format binaire pour le fichier, afin qu'il puisse être lu et écrit par Java et python dans un tableau d'octets. En regardant l'implémentation actuelle (en mars 2019) de python jvm, il semblait être copié en mémoire lors de la réception d'un objet Java et de sa conversion en objet python. Par conséquent, l'échange de données avec des tableaux d'octets nécessite une sérialisation et une désérialisation, mais seule la sérialisation vers des tableaux d'octets en Java est coûteuse.

Échange de données Java et Python dans des tableaux d'octets

Ajoutez une fonction à la classe Java qui crée un tableau d'octets.

  /**
   *Préparez une fonction pour créer un tableau d'octets de Arrow à essayer.
   */
  public static byte[] createArrowFile() throws IOException {
    RootAllocator allocator = new RootAllocator( Integer.MAX_VALUE );
    BitVector vector = new BitVector( "test" , allocator );
    vector.allocateNew( 1 );
    vector.setSafe( 0 , 1 );
    vector.setValueCount( 1 );

    List list = new ArrayList();
    list.add( vector );

    VectorSchemaRoot root = new VectorSchemaRoot( list );
    root.setRowCount( 1 );

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ArrowFileWriter writer = new ArrowFileWriter( root, null, Channels.newChannel( out ) );
    writer.start();
    writer.writeBatch();
    writer.end();
    writer.close();
    return out.toByteArray();
  }

Compilez cette classe et redémarrez-la. Le traitement en python est modifié pour obtenir RecordBatch à partir du tableau d'octets.

from py4j.java_gateway import JavaGateway
import pyarrow as pa
import pyarrow.jvm as j
from pyarrow import RecordBatch

gateway = JavaGateway()

reader = pa.RecordBatchFileReader( pa.BufferReader( gateway.jvm.Py4jExample.createArrowFile() ) )
rb = reader.get_record_batch(0);

df = rb.to_pandas()

print df

Comme prévu, le résultat de cette exécution était que VectorSchemaRoot créé en Java pouvait être traité comme RecordBatch en python.

 $ python test2.py
   test
0  True

Résumé

L'échange de données entre Java et python est maintenant devenu une implémentation de force brute. Cependant, Apache Arrow présente l'avantage d'être compatible avec les bibliothèques qui traitent les données avec python telles que les pandas, et que vous n'avez pas à implémenter votre propre sérialisation et désérialisation.

Le but de cette recherche était de rendre le format de fichier que nous développons actuellement implémenté en Java et également disponible en python, qui est couramment utilisé dans le traitement des données. La prochaine fois, sur la base de cette recherche, j'aimerais écrire un exemple d'implémentation et de fonctionnement de la lecture et de l'écriture de python dans un format de fichier avec un tableau d'octets.

Recommended Posts

Étudiez l'échange de données Java et Python avec Apache Arrow
Construction de pipeline de données avec Python et Luigi
CentOS 6.4, Python 2.7.3, Apache, mod_wsgi, Django
Communication de données chiffrées entre Python et C #
Analyse de données avec python 2
Analyse de données avec Python
Benchmarks langage C, Java, Python avec factorisation prime
Exemple de données créées avec python
Programmation avec Python et Tkinter
Chiffrement et déchiffrement avec Python
Python et matériel - Utilisation de RS232C avec Python -
Apache mod_auth_tkt et Python AuthTkt
Obtenez des données Youtube avec python
J'ai comparé Java et Python!
python avec pyenv et venv
Fonctionne avec Python et R
Lire des données json avec python
Nombre de mots avec Apache Spark et python (Mac OS X)
Débarrassez-vous des données sales avec Python et les expressions régulières
Résolution avec Ruby, Perl, Java et Python AtCoder ATC 002 A
Résolvez le livre en spirale (algorithme et structure de données) avec python!
Résolution avec Ruby, Perl, Java et Python AtCoder ATC 002 B
Obtenez des données supplémentaires vers LDAP avec python (Writer et Reader)
Communiquez avec FX-5204PS avec Python et PyUSB
Briller la vie avec Python et OpenCV
Différence entre java et python (mémo)
Robot fonctionnant avec Arduino et python
Installez Python 2.7.9 et Python 3.4.x avec pip.
Comparaison de la grammaire de base entre Java et Python
Réseau neuronal avec OpenCV 3 et Python 3
Modulation et démodulation AM avec python
Créer Apache Log CSV avec Python
Scraping avec Node, Ruby et Python
Grattage avec Python, Selenium et Chromedriver
Grattage avec Python et belle soupe
[Python] Obtenez des données économiques avec DataReader
Obtenez des données de VPS MySQL avec Python 3 et SQL Alchemy
Encodage et décodage JSON avec python
[GUI en Python] PyQt5-Glisser-déposer-
Structure de données Python apprise avec la chimioinfomatique
Hashing de données en R et Python
Lire et écrire NetCDF avec Python
J'ai joué avec PyQt5 et Python3
AtCoder ARC104 B Somme cumulative résolue en Ruby, Python et Java
Répertorier les chaînes de fractionnement et de jointure avec fractionnement et jointure (Perl / PowerShell / Java / Kotlin / Python)
Visualisez facilement vos données avec Python seaborn.
Lire et écrire du CSV avec Python
Déplacer les données vers LDAP avec python Change / Delete (Writer et Reader)
Intégration multiple avec Python et Sympy
Résolution avec Ruby, Perl, Java et Python AtCoder ABC 065 C-th power
Jusqu'à ce que Python fonctionne sur Apache
Traiter les données Pubmed .xml avec python
Analyse de données à partir de python (visualisation de données 1)
Coexistence de Python2 et 3 avec CircleCI (1.0)
Analyse de données à partir de python (visualisation de données 2)
Application de Python: Nettoyage des données Partie 2: Nettoyage des données à l'aide de DataFrame
Jeu Sugoroku et jeu d'addition avec Python
Modulation et démodulation FM avec Python
Accédez à l'API Web avec Python et enregistrez / acquérez des données IoT (dweet.io, Requests, HTTPie)