我想一次从Python的文件/流中读取多个JSON对象。不幸的是json.load()刚刚.read()s,至文件结束-; 似乎没有任何方法可以使用它来读取单个对象或延迟迭代这些对象。
json.load()
.read()
有什么办法吗?使用标准库将是理想的选择,但是如果有第三方库,我会改用它。
目前,我将每个对象放在单独的行上并使用json.loads(f.readline()),但我真的不希望这样做。
json.loads(f.readline())
import my_json as json import sys for o in json.iterload(sys.stdin): print("Working on a", type(o))
{"foo": ["bar", "baz"]} 1 2 [] 4 5 6
$ python3.2 example.py < in.txt Working on a dict Working on a int Working on a int Working on a list Working on a int Working on a int Working on a int
这是一个非常简单的解决方案。秘诀是尝试,失败并使用异常中的信息正确解析。唯一的限制是该文件必须可搜索。
def stream_read_json(fn): import json start_pos = 0 with open(fn, 'r') as f: while True: try: obj = json.load(f) yield obj return except json.JSONDecodeError as e: f.seek(start_pos) json_str = f.read(e.pos) obj = json.loads(json_str) start_pos += e.pos yield obj
编辑:只是注意到这仅适用于Python> = 3.5。对于更早的版本,失败返回ValueError,并且您必须从字符串中解析出位置,例如
def stream_read_json(fn): import json import re start_pos = 0 with open(fn, 'r') as f: while True: try: obj = json.load(f) yield obj return except ValueError as e: f.seek(start_pos) end_pos = int(re.match('Extra data: line \d+ column \d+ .*\(char (\d+).*\)', e.args[0]).groups()[0]) json_str = f.read(end_pos) obj = json.loads(json_str) start_pos += end_pos yield obj