You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PySpark中记录Python Egg包版本(pkg_resources报DistributionNotFound)

解决PySpark环境中无法获取Python包版本的问题

这个问题我在日常工作中碰到过好几次——PySpark集群环境里pkg_resources.get_distribution()抛出DistributionNotFound,但本地Python环境完全正常。核心原因是Spark Executor的Python环境和Driver端的隔离性,以及包分发时元数据可能没被正确同步到Executor节点。下面给你几个实用的解决方案,按推荐程度排序:

1. 硬编码版本号到包的__init__.py(最稳妥)

这是我最推荐的方案,完全避开环境依赖问题。具体操作:

  • 在你的包根目录(比如mypackagename/__init__.py)里添加一行:
    __version__ = "1.2.3"  # 替换成你的实际版本
    
  • 然后在setup.py里读取这个版本号,避免重复维护:
    from mypackagename import __version__
    
    setup(
        name="mypackagename",
        version=__version__,
        # 其他配置...
    )
    
  • 之后在代码里直接导入使用:
    from mypackagename import __version__
    print(f"当前包版本:{__version__}")
    

这种方法的优势是不依赖任何包元数据查询工具,不管是Driver还是Executor,只要能导入你的包就能拿到版本号,完全不会有环境适配问题。如果怕手动改版本号麻烦,可以搭配setuptools-scm工具自动从Git标签生成版本号,同步到__init__.py里。

2. 确保包元数据随作业分发

如果你坚持要用pkg_resources或者importlib.metadata,那得保证Executor节点能拿到包的完整元数据:

  • 首先,在setup.py里开启include_package_data=True,确保打包时包含PKG-INFO等元数据文件:
    setup(
        # 其他配置...
        include_package_data=True,
    )
    
  • 然后提交Spark作业时,不要只依赖集群上预安装的包,而是用--py-files参数带上你的包的egg/wheel文件:
    spark-submit --py-files mypackagename-1.2.3-py3-none-any.whl your_job.py
    

或者通过Spark配置指定:

from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .config("spark.submit.pyFiles", "mypackagename-1.2.3-py3-none-any.whl") \
    .getOrCreate()

这样Executor启动时会自动安装这个包,元数据也会被正确加载,pkg_resources.get_distribution("mypackagename")就能正常工作了。

3. 改用标准库importlib.metadata替代pkg_resources

pkg_resources是setuptools的旧模块,Python 3.8+已经内置了importlib.metadata作为标准库替代,兼容性更好。你可以写一个兼容不同Python版本的版本获取函数:

def get_package_version(package_name):
    try:
        from importlib.metadata import version
    except ImportError:
        # 针对Python 3.7及以下,需要先安装importlib_metadata包
        from importlib_metadata import version
    return version(package_name)

# 使用
print(get_package_version("mypackagename"))

当然,这个方法依然需要确保Executor节点的环境里有包的元数据,所以还是要配合上面提到的包分发方式。

总结一下:如果追求稳定可靠,优先用硬编码版本号的方案;如果必须动态获取版本,那就确保包元数据随作业正确分发,再用importlib.metadata替代老旧的pkg_resources。

内容的提问来源于stack exchange,提问作者Scott Willeke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:30:08