87 votes

python : lire les lignes des fichiers texte compressés

Est-il facile de lire une ligne d'un fichier texte compressé en gz en utilisant python sans extraire le fichier complètement ? J'ai un fichier text.gz qui fait environ 200 mb. Lorsque je l'extrais, il devient 7,4 Go. Et ce n'est pas le seul fichier que je dois lire. Pour l'ensemble du processus, je dois lire 10 fichiers. Bien que ce soit un travail séquentiel, je pense qu'il serait judicieux de le faire sans extraire toute l'information. Je ne sais même pas si c'est possible. Comment peut-on le faire en utilisant Python ? J'ai besoin de lire un fichier texte ligne par ligne.

120voto

mescalinum Points 82

Utilisation de gzip.GzipFile :

import gzip

with gzip.open('input.gz','rt') as f:
    for line in f:
        print('got line', line)

Note : gzip.open(filename, mode) est un alias pour gzip.GzipFile(filename, mode) . Je préfère le premier, car il ressemble à with open(...) as f: utilisé pour l'ouverture de fichiers non compressés.

51voto

smichak Points 1435

Vous pouvez utiliser le module gzip standard de python. Il suffit d'utiliser :

gzip.open('myfile.gz')

pour ouvrir le fichier comme n'importe quel autre fichier et lire ses lignes.

Plus d'informations ici : Module gzip Python

22voto

jrennie Points 1214

Avez-vous essayé d'utiliser gzip.GzipFile ? Les arguments sont similaires à open .

4voto

Cão Points 61

La bibliothèque gzip utilise (évidemment) gzip ce qui peut être un peu lent. Vous pouvez accélérer les choses avec un appel système à pigz la version parallélisée de gzip . Les inconvénients sont que vous devez installer pigz et il prendra plus de cœurs pendant l'exécution, mais il est beaucoup plus rapide et ne nécessite pas plus de mémoire. L'appel au fichier devient alors os.popen('pigz -dc ' + filename) au lieu de gzip.open(filename,'rt') . Les drapeaux pigz sont -d pour la décompression et -c pour une sortie stdout qui peut ensuite être saisie par os.popen .

Le code suivant prend un fichier et un numéro (1 ou 2) et compte le nombre de lignes dans le fichier avec les différents appels tout en mesurant le temps que prend le code. En définissant le code suivant dans le fichier unzip-file.py :

#!/usr/bin/python
import os
import sys
import time
import gzip

def local_unzip(obj):
    t0 = time.time()
    count = 0
    with obj as f:
        for line in f:
            count += 1
    print(time.time() - t0, count)

r = sys.argv[1]
if sys.argv[2] == "1":
    local_unzip(gzip.open(r,'rt'))
else:
    local_unzip(os.popen('pigz -dc ' + r))

Appeler ces derniers en utilisant /usr/bin/time -f %M qui mesure l'utilisation maximale de la mémoire du processus sur un fichier de 28G que nous obtenons :

$ /usr/bin/time -f %M ./unzip-file.py $file 1
(3037.2604110240936, 1223422024)
5116

$ /usr/bin/time -f %M ./unzip-file.py $file 2
(598.771901845932, 1223422024)
4996

On constate que l'appel système est environ cinq fois plus rapide (10 minutes contre 50 minutes) en utilisant pratiquement la même mémoire maximale. Il est également intéressant de noter que, selon ce que vous faites, la lecture par ligne dans le fichier peut ne pas être le facteur limitant, auquel cas l'option que vous prenez n'a pas d'importance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X