web-dev-qa-db-fra.com

Comment lire du JSON délimité par des lignes à partir d'un fichier volumineux (ligne par ligne)

J'essaie de charger un gros fichier (2 Go) rempli de chaînes JSON, délimité par des retours à la ligne. Ex:

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

La façon dont je l'importe maintenant est:

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

Ce qui semble être un hack (ajouter des virgules entre chaque chaîne JSON et également un crochet carré de début et de fin pour en faire une liste appropriée).

Existe-t-il une meilleure façon de spécifier le délimiteur JSON (newline \n au lieu d'une virgule ,)?

De plus, Python ne semble pas allouer correctement la mémoire pour un objet construit à partir de 2 Go de données, existe-t-il un moyen de construire chaque JSON objet pendant que je lis le fichier ligne par ligne? Merci!

21
Cat

Il suffit de lire chaque ligne et de construire un objet json à ce moment:

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

De cette façon, vous chargez un objet json complet approprié (à condition qu'il n'y ait pas de \n dans une valeur json quelque part ou au milieu de votre objet json) et vous évitez les problèmes de mémoire car chaque objet est créé en cas de besoin.

Il y a aussi cette réponse:

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

Cela fonctionnera pour le format de fichier spécifique que vous avez donné. Si votre format change, vous devrez modifier la façon dont les lignes sont analysées.

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

Il suffit de lire ligne par ligne et de construire les blocs JSON au fur et à mesure:

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 = []

Si vous souhaitez analyser un fichier JSON très volumineux sans tout enregistrer en mémoire, vous devez envisager d'utiliser les méthodes de rappel object_hook ou object_pairs_hook dans l'API json.load.

6
Dane White

Il suffit de le lire ligne par ligne et d'analyser e à travers un flux pendant que votre astuce de piratage (en ajoutant des virgules entre chaque chaîne JSON et également un crochet carré de début et de fin pour en faire une liste appropriée) n'est pas compatible avec la mémoire si le fichier est trop plus de 1 Go car tout le contenu atterrira sur la RAM.

0
Jim