Dieses Mal habe ich Apache Arrow verwendet, um den Datenaustausch zwischen Java und Python zu untersuchen.
Es wird erwartet, dass der Datenaustausch mit Apache Arrow zwischen Systemen und Sprachen kopiert werden kann, ohne in den Speicher zu kopieren. Um die Schlussfolgerung zuerst zu schreiben, wurde sie in dieser Untersuchung über ein Byte-Array im Apache Arrow-Format ausgetauscht. Sie müssen es nicht auf Ihre lokale Festplatte schreiben, aber die Java-Serialisierung und die Python-Deserialisierung führen zum Kopieren von Daten im Speicher. Ich denke, der Vorteil der diesmal eingeführten Methode ist, dass es einfach ist, zwischen Sprachen zu verknüpfen, da es ein allgemeines Hochgeschwindigkeitsformat namens Apache Arrow gibt.
Apache Arrow hatte eine Bibliothek namens jvm für den Datenaustausch zwischen Java und 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
"""
<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>
$ mvn dependency:copy-dependencies -DoutputDirectory=./lib -f ./pom.xml
Erstellen Sie eine einfache Java-Klasse, indem Sie sich auf das Beispiel py4j beziehen. Es implementiert auch eine Funktion, die VecotrSchemaRoot zur Validierung auf py4j zurückgibt.
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();
}
/**
*Bereiten Sie eine Funktion vor, um einen VectorSchemaRoot zum Ausprobieren zu erstellen.
*/
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;
}
}
Kompilieren und starten.
$ javac -cp lib/*:. Py4jExample.java
$ java -cp lib/*:. Py4jExample &
Nachdem wir nun bereit sind, von Python aus aufzurufen, schreiben wir den Python-Prozess.
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()
Ich dachte, es wäre einfach, mit der folgenden JVM-Bibliothek von Java in Pythons record_batch zu konvertieren ...
$ python test.py
Segmentation fault
Sie können es bis zu dem Punkt ausführen, an dem Sie RecordBatch erhalten, aber es scheint abzustürzen, wenn Sie to_pandas () aufrufen. Ich kann nicht sagen, ob meine Umgebung schlecht war, aber ich schien es nicht sofort zu verstehen, also beschloss ich, diesmal aufzugeben.
Alternativ implementiert Apache Arrow auch ein Binärformat für die Datei, sodass sie von Java und Python in einem Byte-Array gelesen und geschrieben werden kann. Mit Blick auf die aktuelle (Stand 03.03.2019) Python-JVM-Implementierung schien sie beim Empfang eines Java-Objekts und beim Konvertieren in ein Python-Objekt im Speicher zu kopieren. Daher erfordert der Datenaustausch mit Byte-Arrays eine Serialisierung und Deserialisierung, aber nur die Serialisierung mit Byte-Arrays in Java ist kostspielig.
Fügen Sie der Java-Klasse eine Funktion hinzu, die ein Byte-Array erstellt.
/**
*Bereiten Sie eine Funktion vor, um ein Byte-Array von Arrow zu erstellen.
*/
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();
}
Kompilieren Sie diese Klasse und starten Sie sie erneut. Die Verarbeitung in Python wird geändert, um RecordBatch aus dem Byte-Array abzurufen.
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
Wie erwartet konnte ich VectorSchemaRoot, das in Java erstellt wurde, als RecordBatch in Python verarbeiten.
$ python test2.py
test
0 True
Der Datenaustausch zwischen Java und Python ist mittlerweile zu einer Brute-Force-Implementierung geworden. Apache Arrow hat jedoch den Vorteil, dass es mit Bibliotheken kompatibel ist, die Daten mit Python wie Pandas verarbeiten, und dass Sie keine eigene Serialisierung und Deserialisierung implementieren müssen.
Der Zweck dieser Forschung war es, das derzeit entwickelte Dateiformat in Java zu implementieren und auch in Python verfügbar zu machen, das üblicherweise in der Datenverarbeitung verwendet wird. Basierend auf dieser Forschung möchte ich das nächste Mal ein Implementierungs- und Operationsbeispiel für das Lesen und Schreiben von Python in ein Dateiformat mit einem Byte-Array schreiben.
Recommended Posts