Comment traiter des fichiers JSON volumineux en Python

Si vous devez traiter un fichier JSON (JavaScript Object Notation) volumineux en Python, il est très facile de manquer de mémoire. Même si les données brutes tiennent théoriquement dans la mémoire, le chargement en Python peut augmenter encore plus l’utilisation de la mémoire. La conséquence étant que soit le traitement sera de plus en plus lent, car l’écriture des données en mémoire vive (RAM) s’effectue sur le disque (mémoire virtuelle), soit un plantage lorsqu’il n’y aura plus de mémoire disponible.

Traitement de fichier volumineux au format JSON

Il y a plusieurs façons de traiter des fichiers JSON volumineux en Python. Voici quelques options que vous pouvez envisager :

  1. Utiliser la bibliothèque json de Python : cette bibliothèque vous permet de charger et d’écrire des données JSON en utilisant des objets Python standard tels que des dictionnaires et des listes. Vous pouvez utiliser la fonction json.loads() pour charger des données JSON à partir d’une chaîne de caractères, et la fonction json.dump() pour écrire des données JSON dans un fichier.
    Cependant, cette approche peut ne pas être efficace pour des fichiers très volumineux, car elle charge toutes les données dans la mémoire avant de les traiter.
  2. Utiliser la bibliothèque ijson : cette bibliothèque vous permet de parser de manière itérative des fichiers JSON volumineux en utilisant un parseur de flux (streaming parser). Vous pouvez utiliser la fonction ijson.parse() pour parser le fichier JSON, et itérer sur les éléments du fichier pour traiter les données au fur et à mesure. Cette approche est plus efficace pour les fichiers volumineux, car elle ne charge pas toutes les données en mémoire à la fois.
  3. Utiliser la bibliothèque pandas : si vous avez besoin de traiter des données tabulaires, vous pouvez utiliser la bibliothèque pandas pour charger des fichiers JSON volumineux dans un DataFrame. Vous pouvez utiliser la fonction pandas.read_json() pour charger le fichier JSON dans un DataFrame, puis utiliser les différentes fonctions de traitement de données de pandas pour manipuler et traiter les données. Cette approche est très efficace pour le traitement de données tabulaires, mais peut être moins adaptée pour des structures de données plus complexes.

Je vous propose dans cet article de voir comment utiliser la bibliothèque Python ijson pour le traitement de fichiers volumineux au format JSON.

ijson, solution de parseur de flux (streaming parser)

Il est évident que charger l’intégralité d’un fichier JSON en mémoire est très consommateur de mémoire. Avec un fichier volumineux, il est même impossible de tout charger.

Dans le cas d’un fichier JSON structuré comme une liste d’objets, nous pourrions théoriquement le parser par morceaux au lieu de tout parser en une seule fois. L’API qui en résulterait permettrait de traiter les objets un par un. Et si nous regardons l’algorithme que nous voulons exécuter, cela convient très bien ; l’algorithme n’exige pas que toutes les données soient chargées en mémoire en même temps. Nous pouvons traiter les enregistrements un par un.

Quel que soit le terme utilisé pour décrire cette approche streaming, analyse itérative, chunking, ou parseur de flux, cela signifie que nous pouvons réduire l’utilisation de la mémoire aux données / à l’enregistrement en cours de traitement, qui devraient généralement être fixes.

À titre d’exemple, nous utiliserons ce fichier de test JSON large-file.json. Il est suffisamment volumineux (env. 24 Mo) pour avoir un impact notable sur la mémoire lors de son chargement. Il encode une liste d’objets JSON décrivant des événements liés à des utilisateurs GitHub.

Fichier JSON volumineux
Large-file.json: Exemple de fichier volumineux JSON

Assurez-vous que le module ijson est installé en exécutant : pip install ijson

L’utilisation la plus courante consiste à faire en sorte que ijson produise nativement des objets Python à partir d’un flux JSON situé sous un préfixe. Cela se fait à l’aide de la fonction items. Voici avec le script ci-dessous comment nous pouvons parcourir un fichier JSON volumineux sans avoir à le charger entièrement en mémoire.

Vous devriez voir qu’il affiche les utilisateurs Github avec le nom de la repository au fur et à mesure, et lorsqu’il a terminé, il vous indiquera qu’il y a 5 250 utilisateurs.

# https://github.com/ICRAR/ijson
import ijson

user_to_repos = {}

with open("large-file.json", "rb") as f:
    for record in ijson.items(f, "item"):
        user = record["actor"]["login"]
        repo_name = record["repo"]["name"]
        if user not in user_to_repos:
            user_to_repos[user] = repo_name

print(f"Il y a {len(user_to_repos)} utilisateurs dans le fichier de données JSON.")

Laisser un commentaire