使用Python API上传文件到Databricks DBFS的报错问题排查
问题根因
两个报错都是Python类型处理不匹配导致的,和Databricks API本身无关:
- 第一个
TypeError: a bytes-like object is required, not 'str':base64.standard_b64encode入参必须是字节(bytes)类型,默认文本模式打开文件读到的是字符串(str),自然报错,改成rb二进制模式读文件的操作是正确的。 - 第二个
TypeError: Object of type 'bytes' is not JSON serializable:base64编码完成后返回的结果仍然是bytes类型,而Python的JSON序列化器不支持直接处理bytes对象,所以构造请求体阶段就失败了。至于跳过base64编码直接传原始文件块的操作完全不符合API参数规范,DBFS拿不到有效文件数据,当然只会生成0字节空文件。
修复方法
核心改动只有一处:base64编码得到bytes结果后,调用.decode('utf-8')转成普通字符串,再传入请求参数即可,其余逻辑不需要调整。
修正后的可运行代码:
import requests import base64 DOMAIN = '<databricks-instance>' TOKEN = '<your-token>' BASE_URL = f'https://{DOMAIN}/api/2.0/dbfs/' def dbfs_rpc(action, body): resp = requests.post( f'{BASE_URL}{action}', headers={'Authorization': f'Bearer {TOKEN}'}, json=body ) resp.raise_for_status() return resp.json() # 创建上传句柄,建议路径带上.csv后缀方便后续识别 handle = dbfs_rpc("create", {"path": "/temp/upload_large_file.csv", "overwrite": "true"})['handle'] with open('./sample.csv', 'rb') as f: while True: # 单块大小严格控制在1MB以内,符合API限制 block = f.read(1 << 20) if not block: break # 编码后转字符串,满足JSON序列化要求 encoded_data = base64.standard_b64encode(block).decode('utf-8') dbfs_rpc("add-block", {"handle": handle, "data": encoded_data}) # 关闭句柄才会最终落盘文件 dbfs_rpc("close", {"handle": handle})
补充说明
- 代码里加了
resp.raise_for_status(),请求出错(比如权限不足、块大小超限、句柄失效)时会直接抛出HTTP错误,方便排查问题,原示例代码漏了这层错误处理,API返回错误时会直接因为拿不到handle字段报KeyError - 上传完成后可以调用
dbfs_rpc("get-status", {"path": "/temp/upload_large_file.csv"})对比返回的file_size字段和本地文件大小,确认上传没有丢数据 - 所有类型的文件(CSV、压缩包、二进制模型文件等)都可以用这个逻辑上传,不需要针对文件格式做特殊处理,保持二进制读取即可
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

