Databricks中使用zipfile写入Zip文件时遇[Errno 95]不支持操作错误求助
Databricks中zipfile写入挂载目录报[Errno 95] Operation not supported的解决方法
问题原因
挂载到DBFS的目录底层基于对象存储(如S3、ADLS Gen2等),这类存储遵循对象存储协议,不支持POSIX文件系统的随机写/seek()操作。而Python标准库的zipfile模块在创建压缩包时,需要多次调用seek()来更新zip文件的目录记录,直接写入挂载目录就会触发该错误。
解决方案
方案1:本地临时目录中转(适合小文件场景)
利用Databricks节点的本地存储(POSIX兼容)生成zip包,再复制到挂载目录,绕开对象存储的限制:
import os import zipfile import shutil # 源文件路径(挂载目录) model_path = '/dbfs/mnt/temp/zip/' # 本地临时zip路径(每个进程独立,避免冲突) local_temp_zip = f'/tmp/demo_{os.getpid()}.zip' # 目标挂载路径 target_zip_path = '/dbfs/mnt/temp/compressed/demo.zip' # 遍历获取所有需要压缩的文件 filenames = [os.path.join(root, name) for root, dirs, files in os.walk(model_path, topdown=False) for name in files] # 在本地生成压缩包 with zipfile.ZipFile(local_temp_zip, 'w', zipfile.ZIP_DEFLATED) as myzip: for filename in filenames: # 生成zip内的相对路径,避免/dbfs前缀 arcname = os.path.relpath(filename, model_path) myzip.write(filename, arcname) # 将本地zip复制到挂载目录 shutil.copy(local_temp_zip, target_zip_path) # 清理本地临时文件 os.remove(local_temp_zip)
方案2:分布式压缩(避免Driver单点压力,适合大文件场景)
通过Spark的分布式能力让每个Executor处理部分文件,生成分区zip,彻底规避Driver瓶颈:
from pyspark.sql import SparkSession import zipfile import os import shutil spark = SparkSession.builder.getOrCreate() # 源文件路径(挂载目录) model_path = '/dbfs/mnt/temp/zip/' # 目标挂载目录 target_dir = '/dbfs/mnt/temp/compressed/' # 将文件列表转为RDD,按分区拆分 file_rdd = spark.sparkContext.parallelize( [os.path.join(root, name) for root, dirs, files in os.walk(model_path, topdown=False) for name in files], numSlices=8 # 根据文件总数调整分区数 ) def compress_partition(file_list): # 每个分区在本地生成独立zip partition_id = spark.sparkContext.partitionId() local_zip = f'/tmp/partition_{partition_id}.zip' with zipfile.ZipFile(local_zip, 'w', zipfile.ZIP_DEFLATED) as zf: for file_path in file_list: # 保留文件相对路径结构 arcname = os.path.relpath(file_path, model_path) zf.write(file_path, arcname) # 上传到挂载目录 shutil.copy(local_zip, f'{target_dir}/partition_{partition_id}.zip') # 清理本地临时文件 os.remove(local_zip) # 执行分布式压缩 file_rdd.foreachPartition(compress_partition)
注意事项
- 禁止直接在挂载的对象存储路径上使用
zipfile执行写操作,必须通过本地存储中转 - 分布式方案生成的是多个分区zip,若需要合并为单个zip,可后续通过Driver或另一个分布式任务处理(大文件合并建议使用专门的分布式压缩工具)
内容的提问来源于stack exchange,提问作者Sharma
相关产品推荐
相关产品推荐

