首页 > 解决方案 > Pyspark 工作人员无法找到 cython 依赖项

问题描述

我正在使用 Cython 对一些 Pyspark 代码进行二进制混淆的项目。我对访问 Cython 依赖项的 spark 工作人员有疑问。

我试图简化项目。这是代码的结构:


├── main.py
├── modules
│   ├── __init__.py
│   ├── toolbox.cpython-38-darwin.so
│   └── toolbox.pyx
├── pyspark_script.cpython-38-darwin.so
├── pyspark_script.pyx
└── setup.py

基本上,我有一个main.py脚本调用已编译的 pyspark 脚本 ( ),该脚本本身通过高阶函数pyspark_script.cpython-38-darwin.so从工作人员使用的已编译模块 () 中导入一些函数。modules.toolbox.cpython-38-darwin.somap

from modules.toolbox import add_one
from modules import toolbox
from modules import product

from pyspark import SparkContext
from pyspark.sql import SQLContext, Row

x = 1
print(f"{x} turns into {toolbox.add_one(x)}")

sc = SparkContext(appName="TestModules")
res_rdd = sc.parallelize(range(0, 10), 3).map(add_one))
print(f"result: {res_rdd.collect()}")

我的问题如下:

  1. 我使用以下 setup.py 文件对我的 spark 代码和工具箱模块进行 cythonnize:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension("pyspark_script", ["pyspark_script.pyx"]),
    Extension("modules.toolbox", ["modules/toolbox.pyx"]),
]

setup(name="Sample Program", cmdclass={"build_ext": build_ext}, ext_modules=ext_modules)
  1. 我编译依赖项:

$ python setup.py build_ext --inplace

  1. 我使用以下命令将其提交给 spark:

$ spark-submit --py-files modules/toolbox.cpython-38-darwin.so --master spark://localhost:7077 main.py

  1. 我有一个错误:工人找不到模块:
21/09/22 18:34:21 WARN TaskSetManager: Lost task 1.0 in stage 1.0 (TID 4) (127.0.0.1 executor 1): org.apache.spark.api.python.PythonException: Traceback (most recent call last):
  File "/usr/local/Cellar/apache-spark/3.1.2/libexec/python/lib/pyspark.zip/pyspark/worker.py", line 586, in main
    func, profiler, deserializer, serializer = read_command(pickleSer, infile)
  File "/usr/local/Cellar/apache-spark/3.1.2/libexec/python/lib/pyspark.zip/pyspark/worker.py", line 69, in read_command
    command = serializer._read_with_length(file)
  File "/usr/local/Cellar/apache-spark/3.1.2/libexec/python/lib/pyspark.zip/pyspark/serializers.py", line 160, in _read_with_length
    return self.loads(obj)
  File "/usr/local/Cellar/apache-spark/3.1.2/libexec/python/lib/pyspark.zip/pyspark/serializers.py", line 430, in loads
    return pickle.loads(obj, encoding=encoding)
ModuleNotFoundError: No module named 'modules'

    at org.apache.spark.api.python.BasePythonRunner$ReaderIterator.handlePythonException(PythonRunner.scala:517)
    at org.apache.spark.api.python.PythonRunner$$anon$3.read(PythonRunner.scala:652)
...

我发现了一个绕过这个问题的技巧:我在我的安装文件中删除了对模块路径的引用。这意味着以 开头的第 6 行Extension("modules.toolbox", ...变为Extension("toolbox", ....

Toolbox .so 文件将在项目的根目录中可用,我将其手动移动到modules目录中:

$ mv toolbox.cpython-38-darwin.so modules

然后工作人员确实找到了工具箱模块,我得到了正确的结果:

1 turns into 2
(...)
result [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] t
21/09/22 18:31:06 INFO SparkUI: Stopped Spark web UI at http://localhost:4040
(...)

所以,我的问题:

更一般地说,如果有人知道主人和工人如何寻找依赖关系并且它们彼此不同,我会非常感激。

标签: pythonpysparkcythonsetuptools

解决方案


推荐阅读