2017-05-05 3 views
2

Je dois traiter quelques très gros fichiers (> 90 Go chacun). Seule une petite partie des fichiers est importante pour moi. Je veux parcourir les fichiers et écrire les lignes nécessaires dans un autre fichier, donc je n'ai pas besoin de traiter de tels fichiers à chaque fois que j'exécute un test. Chaque ligne est d'environ 1000 caractères.python - traitement de fichiers très volumineux (> 90 Go)

J'utilise le code suivant:

def readFile(inputFile, outputFile): 
    startDate = datetime.datetime.strptime('10/06/2010 00:00:00', '%m/%d/%Y %H:%M:%S') 
    endDate = datetime.datetime.strptime('10/13/2010 23:59:59', '%m/%d/%Y %H:%M:%S') 

    total_lines = 0 

    with open(inputFile, 'r') as a_file: 
     for a_line in a_file: 

      total_lines += 1 

      id, date, content = splitLine(a_line) 

      datetime_object = datetime.datetime.strptime(date, '%m/%d/%Y %H:%M:%S') 

      if (datetime_object > startDate and datetime_object < endDate): 
       appendToFile(outputFile, a_line) 

    return total_lines 

def splitLine(long_string): 
    values = long_string.split(",") 
    return values[0],values[1],values[2] 

def appendToFile(outputFile, outputString): 
    try: 
     file = open(outputFile, 'a+') 
     file.write(outputString) 
     file.close() 
    except Exception as ex: 
     print("Error writing to file: " + outputFile) 
    return 

Le problème est, à chaque fois que je lance le script, le processus se coince autour 10.000.000th ligne. Lorsque j'utilise la commande htop, je peux voir que Python n'utilise qu'environ 8 Go de RAM lorsqu'il est bloqué, et que la mémoire virtuelle utilisée continue d'augmenter et que le système d'exploitation tue le processus après un certain temps.

J'ai utilisé des fichiers différents, mais aussi Python 2.7 et 3.5. J'ai également essayé d'utiliser with open(inputFile, 'r', 16777216) pour utiliser la mise en mémoire tampon mais le résultat n'a pas changé. Je cours le code sur MacOS Sierra 10.12.4 et la machine a 16GBs de RAM.

Des idées?

+0

Que fait appendToFile() '? Vous devez inclure un exemple complet, qui inclut * tout * le code requis pour reproduire le problème ("[mcve]"). – Carpetsmoker

+0

Ne pas poster votre code dans les commentaires, vous pouvez [modifier] votre question ;-) – Carpetsmoker

+0

@Carpetsmoker édité :) – gokhan

Répondre

0

Ouvrez le fichier en morceaux, jusqu'à ce que vous trouviez ce que vous voulez. Comme ceci:

f = open('yourfile') 

piece = f.read(4096) 
while piece: 
    # Implementation for each piece 
    piece = f.read(4096) 
f.close() 
0

Une manière plus efficace de faire cela serait d'appeler la commande Unix awk de python. Cela fonctionnera sur Mac et Unix.

Vous appelez appelez unix commandes de python comme ceci:

import os 
os.popen('ls -l > result.txt') 

L'exécution de ce code exemple crée un fichier nommé result.txt qui contient la sortie de la commande ls -l. De même, vous pouvez parcourir vos fichiers avec awk et rediriger le résultat vers un autre fichier.

De la page de manuel de awk:

awk

NOM awk - balayage dirigé modèle et le traitement du langage

SYNOPSIS

awk [ -F fs ] [ -v var=value ] [ 'prog' | -f progfile ] [ file ... ] 

DESCRIPTION:

Awk analyse chaque fichier d'entrée pour trouver les lignes correspondant à un ensemble de motifs spécifiés littéralement dans prog ou dans un ou plusieurs fichiers spécifiés comme -f progfile. Avec chaque motif, il peut y avoir une action associée qui sera exécutée lorsqu'une ligne d'un fichier correspond au motif. Chaque ligne correspond à par rapport à la portion de motif de chaque instruction pattern-action; l'action associée est effectuée pour chaque motif correspondant. Le nom du fichier - signifie l'entrée standard. Tout fichier de la forme var = value est traité comme une affectation, pas un nom de fichier, et est exécuté au moment où il aurait été ouvert s'il s'agissait d'un nom de fichier. L'option -v suivie de var = value est une assignation à faire avant que prog soit exécuté; n'importe quel nombre d'options -v peut être présent. L'option -F fs définit le séparateur de champ d'entrée comme étant l'expression régulière fs.

Lisez cette réponse https://unix.stackexchange.com/questions/76805/read-log-file-between-two-dates pour voir comment utiliser awk pour lire les fichiers journaux entre deux dates.