Comment ajouter des fichiers JAR Java tiers à utiliser dans PySpark
J'ai des bibliothèques clientes de base de données tierces en Java. Je veux y accéder via
java_gateway.py
Par exemple: pour faire la classe client (pas un pilote JDBC!) disponible pour le client Python via la passerelle Java:
java_import(gateway.jvm, "org.mydatabase.MyDBClient")
Il n'est pas clair où ajouter les bibliothèques tierces au chemin de classe JVM. J'ai essayé d'ajouter au fichier compute-classpath.sh , mais cela ne semblait pas fonctionner. Je reçois:
Py4jError: Essayer d'appeler un paquet
Aussi, lors de la comparaison avec Hive: les fichiers hive JAR sontpas chargés via le fichier compute-classpath.sh , donc cela me rend suspect. Il semble y avoir un autre mécanisme qui se passe pour configurer le chemin de classe latéral JVM.
9 answers
Vous pouvez ajouter des jars externes comme arguments à pyspark
pyspark --jars file1.jar,file2.jar
Vous pouvez ajouter le chemin d'accès au fichier jar à l'aide de la configuration Spark lors de l'exécution.
Voici un exemple :
conf = SparkConf().set("spark.jars", "/path-to-jar/spark-streaming-kafka-0-8-assembly_2.11-2.2.1.jar")
sc = SparkContext( conf=conf)
Vous pouvez ajouter --jars xxx.jar
lors de l'utilisation de bougies de soumettre
./bin/spark-submit --jars xxx.jar your_spark_script.py
Ou définir la variable d'environnement SPARK_CLASSPATH
SPARK_CLASSPATH='/path/xxx.jar:/path/xx2.jar' your_spark_script.py
your_spark_script.py
a été écrit par pyspark API
Toutes les réponses ci-dessus n'ont pas fonctionné pour moi
Ce que j'avais à faire avec pyspark était
pyspark --py-files /path/to/jar/xxxx.jar
Pour Jupyter Portable:
spark = (SparkSession
.builder
.appName("Spark_Test")
.master('yarn-client')
.config("spark.sql.warehouse.dir", "/user/hive/warehouse")
.config("spark.executor.cores", "4")
.config("spark.executor.instances", "2")
.config("spark.sql.shuffle.partitions","8")
.enableHiveSupport()
.getOrCreate())
# Do this
spark.sparkContext.addPyFile("/path/to/jar/xxxx.jar")
Lien vers la source où je l'ai trouvé: https://github.com/graphframes/graphframes/issues/104
- Extrayez le fichier jar téléchargé.
- Modifier la variable d'environnement système
- Ajouter une variable nommée SPARK_CLASSPATH et définissez sa valeur sur \chemin\vers\le\extraite\jar\fichier.
Par exemple: vous avez extrait le fichier jar dans le lecteur C dans le dossier nommé sparkts sa valeur devrait être: C:\sparkts
- Redémarrez votre cluster
Une autre chose que vous pouvez faire est d'ajouter le Jar dans le dossier jar pyspark où pyspark est installé. Habituellement /python3. 6 / site-packages/pyspark / jars
Soyez prudent si vous utilisez un environnement virtuel dont le jar a besoin pour accéder à l'installation pyspark dans l'environnement virtuel.
De cette façon, vous pouvez utiliser le jar sans l'envoyer en ligne de commande ou le charger dans votre code.
En dehors de la réponse acceptée, vous avez également les options ci-dessous:
-
Si vous êtes dans un environnement virtuel, alors vous pouvez le placer dans
Par exemple
lib/python3.7/site-packages/pyspark/jars
-
Si vous voulez que java le découvre, vous pouvez placer où votre jre est installé sous
ext/
directory
J'ai contourné cela en déposant les jars dans un pilote de répertoire, puis en créant un spark-defaults.fichier conf dans le dossier conf. Étapes à suivre;
To get the conf path:
cd ${SPARK_HOME}/conf
vi spark-defaults.conf
spark.driver.extraClassPath /Users/xxx/Documents/spark_project/drivers/*
Exécutez votre ordinateur portable Jupyter.
Les bibliothèques Java/scala de pyspark --jars
et spark.jars
ne fonctionnent pas dans la version 2.4.0 et les versions antérieures (je n'ai pas vérifié la version plus récente). Je suis surpris de voir combien de gars prétendent que cela fonctionne.
Le problème principal est que pour classloader récupéré de la manière suivante:
jvm = SparkSession.builder.getOrCreate()._jvm
clazz = jvm.my.scala.class
# or
clazz = jvm.java.lang.Class.forName('my.scala.class')
Cela ne fonctionne que lorsque vous copiez des fichiers jar dans {{SPARK_HOME}/jars (celui-ci fonctionne pour moi).
Mais lorsque votre seul moyen est d'utiliser --jars
ou spark.jars
, un autre chargeur de classe est utilisé (qui est le chargeur de classe enfant) qui est défini dans le thread actuel. Si votre code python doit ressembler à:
clazz = jvm.java.lang.Thread.currentThread().getContextClassLoader().loadClass(f"{object_name}$")
J'espère que cela explique vos problèmes. Donnez-moi un cri si pas.