ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Apache Arrow PyArrow JSON 读取实战:read_json 类型推断、ParseOptions/ReadOptions 定制与 open_json 增量解析

Apache Arrow PyArrow JSON 读取实战:read_json 类型推断、ParseOptions/ReadOptions 定制与 open_json 增量解析 Apache Arrow PyArrow JSON 读取实战read_json 类型推断、ParseOptions/ReadOptions 定制与 open_json 增量解析【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow本文基于 Apache Arrow 官方文档 Reading JSON files 展开聚焦 PyArrow 中pyarrow.json模块对行分隔 JSONline-delimited JSON文件的读取能力如何用一行read_json()调用把 JSONL 文件直接变成 Arrow Table、自动类型推断的完整规则与回退策略、通过ParseOptions和ReadOptions定制解析行为以及面向内存受限场景的open_json()逐批RecordBatch增量读取。读完后你可以独立完成 JSON 数据接入 Arrow 全链路分析场景并能结合 C 实现 与 Python 绑定 理解其底层线程模型与 schema 冻结语义。一、格式支持仅行分隔 JSONArrow 支持从行分隔 JSON 文件中读取列式数据。在这种格式中一个 JSON 文件由多个 JSON 对象组成每行一个对象每个对象代表一行数据。官方文档给出的示例文件表示两行、四列a、b、c、d的数据{a: 1, b: 2.0, c: foo, d: false} {a: 4, b: -5.5, c: null, d: true}文档明确指出当前仅支持行分隔 JSON 格式即 JSONL / NDJSON。该格式带来的能力包括多线程或单线程读取基于文件扩展名的自动解压例如my_data.json.gz会自动按压缩格式解压读取精细的类型推断见下文。从 Python 绑定 的open_json文档字符串可以确认解压行为的触发条件当传入字符串或路径且以受识别的压缩扩展名如.gz或.bz2结尾时读取时自动解压。二、快速上手read_json 一把梭JSON 读取功能通过pyarrow.json模块提供——python/pyarrow/json.py 本质上只有一行导出语句把ReadOptions、ParseOptions、read_json、open_json从 Cython 编译的_json模块重新导出from pyarrow._json import ReadOptions, ParseOptions, read_json, open_json # noqa大多数场景下你只需调用read_json()并传入文件路径 from pyarrow import json fn my_data.json table json.read_json(fn) table pyarrow.Table a: int64 b: double c: string d: bool table.to_pandas() a b c d 0 1 2.0 foo False 1 4 -5.5 None Trueread_json()的完整签名见 _json.pyx为read_json(input_file, read_optionsNone, parse_optionsNone, memory_poolNone)input_file字符串、路径或 file-like 对象定位 JSON 数据仅支持行分隔格式read_options/parse_options可选分别控制读取性能与解析行为不传则使用 C 层默认值memory_pool可选指定 Table 内存的分配池。在 Cython 层read_json通过_get_reader把输入统一转换为 ArrowInputStream再用CJSONReader.Make(...)构造 C 的TableReader并调用其Read()一次性读出完整Table。三、自动类型推断JSON 类型到 Arrow 类型的映射规则Arrow 数据类型从每列 JSON 的类型和值中推断完整规则如下继承自官方文档并与 C 转换器 的行为对应JSON 输入推断的 Arrow 类型回退策略null 值null类型可回退到任意其他类型布尔值bool_无数字int64遇到非整数时回退为float64形如 YYYY-MM-DD 或 YYYY-MM-DD hh:mm:ss 的字符串timestamp[s]转换出错时回退为utf8JSON 数组list对数组元素递归推断嵌套 JSON 对象struct对对象字段递归推断官方文档中的嵌套示例可以直观验证递归推断{a: [1, 2], b: {c: true, d: 1991-02-03}} {a: [3, 4, 5], b: {c: false, d: 2019-04-01}} table json.read_json(my_data.json) table pyarrow.Table a: listitem: int64 child 0, item: int64 b: structc: bool, d: timestamp[s] child 0, c: bool child 1, d: timestamp[s] table.to_pandas() a b 0 [1, 2] {c: True, d: 1991-02-03 00:00:00} 1 [3, 4, 5] {c: False, d: 2019-04-01 00:00:00}注意几个关键点全为 null 的列会先推断为null类型只要后续出现其他值即可提升为目标类型因此先 null 后数值的数据不会产生错误类型日期字符串只识别YYYY-MM-DD和YYYY-MM-DD hh:mm:ss两种形态识别为timestamp[s]秒级时间戳解析失败则整列降级为utf8推断是递归的list与struct的嵌套结构可以逐层展开。四、定制解析ParseOptions 的三个参数对于结构特殊的 JSON 文件可以创建ParseOptions实例并传给read_json()。python/pyarrow/_json.pyx 中定义ParseOptions(explicit_schemaNone, newlines_in_valuesNone, unexpected_field_behaviorNone)各参数与默认值默认值来自 C 层 options.h 的ParseOptions::Defaults()explicit_schema默认None显式指定 ArrowSchema。一旦设置将绕过自动类型推断——从源码结构看C 的DecodeContext::SetParseOptions在存在explicit_schema时直接以该 schema 的字段构造目标 struct 类型不再参与推断newlines_in_values默认False是否允许单个对象跨多行输出例如 pretty-printed 格式。绑定层文档特别提示设为True会降低多线程 JSON 读取性能因为块切分不能再简单依赖行边界unexpected_field_behavior默认infer当给定explicit_schema时schema 之外的 JSON 字段如何处理三种取值ignore忽略未预期的 JSON 字段error遇到未预期字段直接报错infer对未预期字段做类型推断并包含到输出中。设置非法取值会立即抛出ValueError见 _json.pyx 的 setter 校验。一个典型用法是传入显式 schema 完全接管类型决定例如把文档示例中的列固定为int64/double/string/bool避免数据中偶发的类型漂移导致列类型不稳定import pyarrow as pa from pyarrow import json schema pa.schema([ (a, pa.int64()), (b, pa.float64()), (c, pa.utf8()), (d, pa.bool_()), ]) table json.read_json(my_data.json, parse_optionsjson.ParseOptions(explicit_schemaschema))Python 测试 中的test_explicit_schema_decimal与test_explicit_schema_with_unexpected_behaviour分别验证了显式 decimal schema 和三种unexpected_field_behavior的实际行为可以作为各取值的参考用例。五、性能调优ReadOptions 的线程与块大小ReadOptions控制读取性能同样在 _json.pyx 中定义ReadOptions(use_threadsNone, block_sizeNone)其默认值在 cpp/src/arrow/json/options.h 中可以直接读到use_threads默认True是否使用全局 CPU 线程池加速读取block_size默认1 20即 1 MB每次从输入流请求的字节数。它同时决定多线程的并行粒度以及Table中各 chunk 的大小。C 侧 StreamingReader 的注释 进一步说明了线程模型use_threads为true时每个块的解析/解码任务会在执行器上并行化预读深度对应执行器容量未提供执行器时使用全局线程池为false时计算直接在调用线程上运行。需要特别注意的是一个常见误区open_json()的流式读取始终是单线程的_json.pyx 的文档字符串明确写着 Reading using this function is always single-threaded多线程并行只存在于read_json()路径。六、增量读取open_json 与 schema 冻结在内存受限环境下可以用open_json()按 RecordBatch 逐批读取 JSON 文件返回一个JSONStreamingReader继承自RecordBatchReader因此支持read_next_batch()、read_all()、close()等标准流式读取接口reader json.open_json(my_data.json) while True: batch reader.read_next_batch() if batch is None: break process(batch) reader.close()open_json()的input_file、read_options、parse_options、memory_pool参数语义与read_json()完全一致签名见 _json.pyx。增量读取有一个关键语义差异类型推断只发生在第一个非空块上之后 schema 即被冻结。C 侧 StreamingReader 的文档注释 描述得最为精确数据以固定大小的块ReadOptions::block_size从流中读取每个块转换为一个RecordBatch各批 schema 一致但行数可以不同若未提供显式 schema目标 schema 由第一个非空块推断得出随后冻结当unexpected_field_behavior为InferType时未预期字段只在第一个块中被推断之后出现新字段将被视为错误。官方文档因此给出两条保证类型正确的建议这里完整保留把ReadOptions.block_size设置为足够大的值让推断覆盖到足够多的数据或者用ParseOptions.explicit_schema显式指定期望的数据类型。Python 测试中的 test_inference 是对schema 冻结语义的最佳实证同一个三行输入{a: 0, b: foo} / {a: 1, c: true} / {a: 2, d: 4.0}在block_size32第一块只含第一行时schema 冻结为a: int64, b: utf8继续读取第二批时因出现新字段c而抛出ArrowInvalid: JSON parse error: unexpected field把block_size调到 64、96 后第一块包含的行数变多冻结的 schema 依次扩展出c: bool与d: float64。这清楚说明流式读取时block_size不只是性能参数更直接影响推断出 schema 的完整性。七、底层实现速览切块、解析、转换三段式从 cpp/src/arrow/json/ 目录结构看C 端把读取过程组织为清晰的流水线Python 绑定只是它的薄封装TableReader对应read_json一次性把整个文件读成TableStreamingReader对应open_json还支持MakeAsync异步构造与ReadNextAsync异步取批以及bytes_processed()进度查询读取主流程reader.cc采用 AsyncGenerator 风格的 transformer 链IO 层产出原始块 →ChunkingTransformer用 Chunker 把字节流切分为完整对象 跨块拼接片段partial/completion/whole三段结构ChunkedBlock定义见 reader.cc→BlockParser完成 JSON 解析 → 转换器按冻结/推断出的 schema 生成RecordBatch。这种按块切分正是block_size能决定 chunk 大小与并行粒度的原因也让newlines_in_valuesTrue时的跨行对象拼接成为必要环节。八、适用前提与限制小结结合文档与源码使用该功能时的注意点仅支持行分隔 JSONpretty-printed 跨行对象需要显式设置ParseOptions(newlines_in_valuesTrue)且会损失多线程性能自动解压按文件扩展名如.gz、.bz2触发仅对字符串/路径输入生效read_json默认多线程use_threadsTrue、1 MB 块open_json恒为单线程open_json的 schema 由第一个非空块冻结后续新字段unexpected_field_behaviorinfer时会报错建议加大block_size或使用explicit_schema时间戳推断只覆盖YYYY-MM-DD与YYYY-MM-DD hh:mm:ss两种字符串形态且仅推断到秒级timestamp[s]更精确的时间列应通过explicit_schema指定类型。相关入口文件供进一步深入官方文档原文、Python 模块导出、Cython 绑定、C 选项定义、C 读取器、Python 测试 与 C 解析器测试。【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表