터미널에서 pyspark 를 치면 다음처럼 죽는다.
python: can't open file '/opt/spark/python/pyspark/shell.py': [Errno 2] No such file or directory
bin/pyspark 는 셸 스크립트다. 내부에서 SPARK_HOME 을 기준으로 $SPARK_HOME/python/pyspark/shell.py 를 파이썬에 넘겨 대화형 세션을 띄운다. 따라서 이 오류는 다음 둘 중 하나다.
첫째, SPARK_HOME 이 실제 설치 경로와 다르다. 예전 경로가 환경변수나 프로필에 남아 있는데 실제 배포본은 다른 자리에 있는 경우다.
둘째, SPARK_HOME 은 맞지만 그 배포본에 파이썬 부분이 없다. 소스에서 빌드하거나 일부만 복사해 온 설치본에는 python/ 디렉터리가 통째로 빠져 있을 수 있다.
먼저 지금 잡힌 값과 실제 파일을 대조한다.
echo "$SPARK_HOME"
which pyspark spark-submit
ls -l "$SPARK_HOME/python/pyspark/shell.py"
ls -d "$SPARK_HOME"/python/lib/py4j-*-src.zip
Spark 3.4 이후에는 shell.py 대신 python/pyspark/shell.py 가 여전히 존재하지만 실행 방식이 조금 다르므로, 파일 유무로만 판단한다.
Cloudera 등 벤더 배포판은 경로가 /opt/cloudera/parcels/CDH/lib/spark3 처럼 parcel 아래에 있다. 직접 내려받은 tarball 과 섞이지 않게 한다.
ls -d /opt/cloudera/parcels/*/lib/spark*
프로필에 세 가지를 둔다.
export SPARK_HOME=/opt/spark
export PATH=$SPARK_HOME/bin:$PATH
export PYTHONPATH=$SPARK_HOME/python:$(ls $SPARK_HOME/python/lib/py4j-*-src.zip):$PYTHONPATH
PYTHONPATH 는 pyspark 셸을 띄우는 데는 필수가 아니지만, 일반 파이썬 스크립트에서 import pyspark 를 하려면 필요하다. py4j 의 버전 문자열이 배포본마다 다르므로 와일드카드로 잡는 편이 안전하다.
드라이버와 실행기가 쓸 파이썬 인터프리터도 명시한다. 둘이 다르면 직렬화 단계에서 깨진다.
export PYSPARK_PYTHON=/usr/bin/python3
export PYSPARK_DRIVER_PYTHON=/usr/bin/python3
pip install pyspark 로 설치한 패키지도 자기 bin/pyspark 를 만든다. tarball 배포본과 섞이면 PATH 앞쪽에 있는 쪽이 이기는데, 그쪽 SPARK_HOME 은 site-packages 안을 가리킨다. 클러스터에 붙일 목적이라면 배포본 쪽을 써야 한다.
pip show pyspark
python -c "import pyspark, os; print(os.path.dirname(pyspark.__file__))"
둘을 함께 둘 이유가 없으면 pip 쪽을 지운다.
pyspark --master local[2]
spark.range(5).show()
클러스터에 붙이려면 HADOOP_CONF_DIR 이 잡혀 있어야 한다. 이 값이 없으면 --master yarn 이 리소스 매니저를 못 찾는다.
export HADOOP_CONF_DIR=/etc/hadoop/conf
pyspark --master yarn --deploy-mode client
--deploy-mode cluster 로는 대화형 셸을 띄울 수 없다. 드라이버가 클러스터 안에서 돌아 표준 입력이 없기 때문이다. 셸은 언제나 client 모드다.
Kerberos 가 켜진 클러스터에서는 kinit 이 먼저다. 티켓 없이 붙으면 셸은 뜨지만 첫 잡 제출에서 인증 오류가 난다.
PYTHONPATH 의 py4j 버전이 어긋날 때.