如何将 JAR 捆绑在 python 包中并使其可用于 pyspark?



我写了一些在SparkDataFrame上运行的Scala代码。我希望我公司的数据科学家能够从PySpark(他们主要在Jupyter笔记本中使用(调用它,因此我围绕它编写了一个薄的Python包装器,它调用Scala代码(通过py4j(,该代码已被编译为JAR(foo.jar(。我已经将罐子和包装器(foo.py(打包成一个Python轮(foo.whl(。

当轮子pip安装时,它可以在/path/to/site-packages/foo,JAR在/path/to/site-packages/foo/jars/foo.jar

在 foo.py 中,我有以下代码将JAR安装到${SPARK_HOME}/jars目录中

package_dir = os.path.dirname(os.path.realpath(__file__))
jar_file_path = os.path.join(package_dir, f"foo/jars/foo.jar")
tgt = f"{os.environ.get('SPARK_HOME')}/jars/foo.jar"
if os.path.islink(tgt):
print(f"Removing existing symlink {tgt}")
os.unlink(tgt)
os.symlink(jar_file_path, tgt)

当我或任何希望使用它的人运行时import foo然后 JAR 被移动到 spark 期望它所在的正确位置,然后可以从 pyspark 代码调用它。一切都很好。

不幸的是,我们的生产环境受到限制,最终用户(理所当然地(没有足够的权限来允许他们影响文件系统,因此当上面的代码尝试创建符号链接时,它会失败并显示权限错误。

这是可以解决的吗?我想:

  • 让我们的数据科学家真正轻松地pip install foo并为他们提供软件包的功能
  • 但也使JAR可用于Spark,而无需将其移动到${SPARK_HOME}

任何人都可以提出修复建议吗?


评论者要求的一些额外信息。我们的Spark集群实际上是GCP DataProc集群(即Google的hadoop/spark托管服务(。数据存储在Google存储桶中(GCS - Google相当于S3(,最终用户(在Jupyter中使用pyspark(确实可以访问这些存储桶。

我相信这就是你要找的。

带有 Python 安装工具的安装后脚本

看起来您要做的是有一个安装脚本,当用户运行 jar 时,该脚本将 jar 文件符号链接到 spark 路径 foo.py。问题是,如果 jvm 已经启动,这将不起作用,而且用户无论如何都没有执行此操作的权限。

相反,您应该做的是将安装后钩子添加到 setup.py 文件中,以便当用户运行pip install时,它将自动执行符号链接。

from setuptools.command.install import install
from setuptools import setup
class PostInstallCommand(install):
"""Post-installation for installation mode."""
def run(self):
install.run(self)
package_dir = os.path.dirname(os.path.realpath(__file__))
jar_file_path = os.path.join(package_dir, f"foo/jars/foo.jar")
tgt = f"{os.environ.get('SPARK_HOME')}/jars/foo.jar"
if os.path.islink(tgt):
print(f"Removing existing symlink {tgt}")
os.unlink(tgt)
os.symlink(jar_file_path, tgt)

然后在 setup.py 中将 cmdclass 参数插入 setup(( 函数:

setup(
...
cmdclass={
'develop': PostDevelopCommand,
'install': PostInstallCommand,
},
...
)

如果你让管理员为数据科学家设置python环境,这应该可以解决权限问题

最新更新