web-dev-qa-db-ja.com

大きなファイルから行区切りのJSONを読み取る方法(行ごと)

改行で区切られたJSON文字列で満たされた大きなファイル(サイズが2GB)をロードしようとしています。例:

{
    "key11": value11,
    "key12": value12,
}
{
    "key21": value21,
    "key22": value22,
}
…

現在インポートする方法は次のとおりです。

content = open(file_path, "r").read() 
j_content = json.loads("[" + content.replace("}\n{", "},\n{") + "]")

これはハックのようです(各JSON文字列の間にコンマを追加し、適切なリストにするために開始および終了の角括弧も追加します)。

JSON区切り文字を指定するより良い方法はありますか(改行\nコンマの代わりに,)?

また、Pythonは2GBのデータから構築されたオブジェクトにメモリを適切に割り当てることができないようです。ファイルを1行ずつ読み取っているときに各JSONオブジェクトを作成する方法はありますか?ありがとう!

21
Cat

この時点で各行を読み取り、jsonオブジェクトを作成するだけです。

with open(file_path) as f:
    for line in f:
        j_content = json.loads(line)

このようにして、適切な完全なjsonオブジェクトをロードします(\nをjson値のどこか、またはjsonオブジェクトの途中で)必要に応じて各オブジェクトが作成されるため、メモリの問題を回避できます。

この答えもあります。

https://stackoverflow.com/a/7795029/67154

28
njzk2
contents = open(file_path, "r").read() 
data = [json.loads(str(item)) for item in contents.strip().split('\n')]
7
Tjorriemorrie

これは、指定した特定のファイル形式で機能します。フォーマットが変更された場合、行の解析方法を変更する必要があります。

{
    "key11": 11,
    "key12": 12
}
{
    "key21": 21,
    "key22": 22
}

行ごとに読んで、JSONブロックを作成していきます:

with open(args.infile, 'r') as infile:

    # Variable for building our JSON block
    json_block = []

    for line in infile:

        # Add the line to our JSON block
        json_block.append(line)

        # Check whether we closed our JSON block
        if line.startswith('}'):

            # Do something with the JSON dictionary
            json_dict = json.loads(''.join(json_block))
            print(json_dict)

            # Start a new block
            json_block = []

すべてをメモリに保存せずに1つの非常に大きなJSONファイルを解析することに興味がある場合は、json.load APIのobject_hookまたはobject_pairs_hookコールバックメソッドの使用を検討する必要があります。

6
Dane White

ファイルが多すぎる場合は、ハッキングトリック(各JSON文字列の間にカンマを追加し、適切なリストにするために角括弧を追加する)しながら、1行ずつ読み、ストリームを介してeを解析しますコンテンツ全体がRAMに格納されるため、1GBを超えます。

0
Jim