python - Configuración de Spark para trabajar con Jupyter Notebook y Anaconda
pyspark jupyter-notebook (3)
He pasado unos días tratando de hacer que Spark funcione con mi Jupyter Notebook y Anaconda. Así es como se ve mi .bash_profile:
PATH="/my/path/to/anaconda3/bin:$PATH"
export JAVA_HOME="/my/path/to/jdk"
export PYTHON_PATH="/my/path/to/anaconda3/bin/python"
export PYSPARK_PYTHON="/my/path/to/anaconda3/bin/python"
export PATH=$PATH:/my/path/to/spark-2.1.0-bin-hadoop2.7/bin
export PYSPARK_DRIVER_PYTHON=jupyter
export PYSPARK_DRIVER_PYTHON_OPTS="notebook" pyspark
export SPARK_HOME=/my/path/to/spark-2.1.0-bin-hadoop2.7
alias pyspark="pyspark --conf spark.local.dir=/home/puifais --num-executors 30 --driver-memory 128g --executor-memory 6g --packages com.databricks:spark-csv_2.11:1.5.0"
Cuando
/my/path/to/spark-2.1.0-bin-hadoop2.7/bin/spark-shell
, puedo iniciar Spark muy bien en mi shell de línea de comando.
Y la salida
sc
no está vacía.
Parece que funciona bien.
Cuando
pyspark
, lanza bien mi Jupyter Notebook.
Cuando creo un nuevo cuaderno de Python3, aparece este error:
[IPKernelApp] WARNING | Unknown error in handling PYTHONSTARTUP file /my/path/to/spark-2.1.0-bin-hadoop2.7/python/pyspark/shell.py:
Y
sc
en mi cuaderno Jupyter está vacío.
¿Alguien puede ayudar a resolver esta situación?
Solo quiero aclarar: no hay nada después de los dos puntos al final del error. También intenté crear mi propio archivo de inicio utilizando esta post y cito aquí para que no tenga que ir a buscar allí:
Creé un breve script de inicialización init_spark.py de la siguiente manera:
from pyspark import SparkConf, SparkContext conf = SparkConf().setMaster("yarn-client") sc = SparkContext(conf = conf)
y lo colocó en el directorio ~ / .ipython / profile_default / startup /
Cuando hice esto, el error se convirtió en:
[IPKernelApp] WARNING | Unknown error in handling PYTHONSTARTUP file /my/path/to/spark-2.1.0-bin-hadoop2.7/python/pyspark/shell.py:
[IPKernelApp] WARNING | Unknown error in handling startup files:
Bueno, realmente me duele ver cómo los hacks de mierda, como configurar
PYSPARK_DRIVER_PYTHON=jupyter
, han sido promovidos a "soluciones" y tienden a convertirse en prácticas estándar, a pesar de que evidentemente conducen a resultados
feos
, como escribir
pyspark
y terminar con un portátil Jupyter en lugar de un shell PySpark, además de problemas aún no vistos que acechan aguas abajo, como cuando
intentas usar
spark-submit
con la configuración anterior
... :(
(No me malinterpretes, no es tu culpa y no te culpo; he visto docenas de publicaciones aquí en SO donde esta "solución" ha sido propuesta, aceptada y votada ...).
Hay una y solo una manera adecuada de personalizar un cuaderno Jupyter para que funcione con otros idiomas (PySpark aquí), y este es el uso de los núcleos Jupyter .
Lo primero que debe hacer es ejecutar un
jupyter kernelspec list
, para obtener la lista de los núcleos ya disponibles en su máquina;
Aquí está el resultado en mi caso (Ubuntu):
$ jupyter kernelspec list
Available kernels:
python2 /usr/lib/python2.7/site-packages/ipykernel/resources
caffe /usr/local/share/jupyter/kernels/caffe
ir /usr/local/share/jupyter/kernels/ir
pyspark /usr/local/share/jupyter/kernels/pyspark
pyspark2 /usr/local/share/jupyter/kernels/pyspark2
tensorflow /usr/local/share/jupyter/kernels/tensorflow
El primer núcleo,
python2
, es el "predeterminado" que viene con IPython (existe una gran posibilidad de que sea el único presente en su sistema);
En cuanto al resto, tengo 2 núcleos Python más (
caffe
y
tensorflow
), uno R (
ir
) y dos núcleos PySpark para usar con Spark 1.6 y Spark 2.0 respectivamente.
Las entradas de la lista anterior son directorios, y cada uno contiene un solo archivo, llamado
kernel.json
.
Veamos el contenido de este archivo para mi núcleo
pyspark2
:
{
"display_name": "PySpark (Spark 2.0)",
"language": "python",
"argv": [
"/opt/intel/intelpython27/bin/python2",
"-m",
"ipykernel",
"-f",
"{connection_file}"
],
"env": {
"SPARK_HOME": "/home/ctsats/spark-2.0.0-bin-hadoop2.6",
"PYTHONPATH": "/home/ctsats/spark-2.0.0-bin-hadoop2.6/python:/home/ctsats/spark-2.0.0-bin-hadoop2.6/python/lib/py4j-0.10.1-src.zip",
"PYTHONSTARTUP": "/home/ctsats/spark-2.0.0-bin-hadoop2.6/python/pyspark/shell.py",
"PYSPARK_PYTHON": "/opt/intel/intelpython27/bin/python2"
}
}
No me he molestado en cambiar mis detalles a
/my/path/to
etc., y ya puede ver que hay algunas diferencias entre nuestros casos (uso Intel Python 2.7 y no Anaconda Python 3), pero espero que obtenga el idea (por cierto, no te preocupes por el archivo de
connection_file
, tampoco uso uno).
Ahora, la forma más fácil para usted sería realizar manualmente los cambios necesarios (solo rutas) en mi kernel que se muestra arriba y guardarlo en una nueva subcarpeta del directorio
.../jupyter/kernels
(de esa manera, debería ser visible si ejecuta de nuevo un comando de
jupyter kernelspec list
).
Y si crees que este enfoque también es un truco, bueno, estaría de acuerdo contigo, pero es el recomendado en la
documentación de Jupyter
(página 12):
Sin embargo, no hay una excelente manera de modificar las especificaciones del núcleo. Un enfoque utiliza la
jupyter kernelspec list
para encontrar el archivokernel.json
y luego lo modifica, por ejemplo,kernels/python3/kernel.json
, a mano.
Si aún no tiene una carpeta
.../jupyter/kernels
, aún puede instalar un nuevo kernel usando
jupyter kernelspec install
, no lo he probado, pero eche un vistazo a
esta respuesta SO
.
Finalmente, no olvide eliminar todas las variables de entorno relacionadas con PySpark de su perfil de bash (dejar solo
SPARK_HOME
debería estar bien).
Y confirme que, cuando escribe
pyspark
, se encuentra con un shell PySpark, como debería ser, y no con un cuaderno Jupyter ...
ACTUALIZACIÓN
(después del comentario): si desea pasar argumentos de línea de comandos a PySpark, debe agregar la configuración
PYSPARK_SUBMIT_ARGS
en
env
;
Por ejemplo, aquí está la última línea de mi archivo kernel respectivo para Spark 1.6.0, donde todavía teníamos que usar el paquete externo spark-csv para leer archivos CSV:
"PYSPARK_SUBMIT_ARGS": "--master local --packages com.databricks:spark-csv_2.10:1.4.0 pyspark-shell"
Conda puede ayudar a gestionar correctamente muchas dependencias ...
Instalar chispa. Suponiendo que spark esté instalado en / opt / spark, inclúyalo en su ~ / .bashrc:
export SPARK_HOME=/opt/spark
export PATH=$SPARK_HOME/bin:$PATH
Cree un entorno conda con todas las dependencias necesarias además de spark:
conda create -n findspark-jupyter-openjdk8-py3 -c conda-forge python=3.5 jupyter=1.0 notebook=5.0 openjdk=8.0.144 findspark=1.1.0
Activar el medio ambiente
$ source activate findspark-jupyter-openjdk8-py3
Inicie un servidor Jupyter Notebook:
$ jupyter notebook
En su navegador, cree una nueva computadora portátil Python3
Intente calcular PI con el siguiente script (tomado de this )
import findspark
findspark.init()
import pyspark
import random
sc = pyspark.SparkContext(appName="Pi")
num_samples = 100000000
def inside(p):
x, y = random.random(), random.random()
return x*x + y*y < 1
count = sc.parallelize(range(0, num_samples)).filter(inside).count()
pi = 4 * count / num_samples
print(pi)
sc.stop()
Después de jugar un poco aquí, acabo de instalar sparkmagic (después de reinstalar una versión más nueva de Spark). Creo que solo eso simplemente funciona.
No estoy seguro, ya que he jugado un poco antes de eso, pero lo estoy colocando como una respuesta tentativa, ya que es mucho más simple que manipular manualmente los archivos de configuración.