IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Manipulation d'un fichier volumineux


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mars 2011
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2011
    Messages : 39
    Par défaut Manipulation d'un fichier volumineux
    Bonjour

    Je travaille actuellement sur le développement d'un package ODI. En gros j'ai des données en entrée, je les traites et je les sauvegardes.

    ici, mon entrée c'est un fichier texte de 5Go, ce fichier ressemble à ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    IDLIBELLEDATEDEBDATEFIN
    01TOTO2012010120120201
    01TATA2012020120120301
    02BOBO2012040120120501
    02BABA2012050120120601
    ..
    09FOFO2013010120130201
    il y a plusieurs millions de lignes pour chaque ID et oui pourquoi faire simple quand on peut faire compliqué.

    Mon besoin et simple: pour que mes tests ODI soient rapides j'ai besoin de réduire le nombre de lignes à environ 10 par ID. je suis sur un PC sans droits admin mais j'ai remarqué que python est installé sur mon poste et je sais que python c'est pas mal pour la manipulation de fichiers. Par contre, le truc le plus poussé que j'ai fait en python c'est un "hello world".

    Merci d'avance

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Est-ce que les ID sont d'une longueur de 2 caractères dans 0..9.
    Dit autrement est-ce qu'on a que 100 ID au plus?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre averti
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mars 2011
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2011
    Messages : 39
    Par défaut
    En effet les ID ne dépasseront jamais 2 caractères, j'ai oublié de le préciser.

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Pour autant que j'ai bien compris, et dans la mesure où c'était intéressant, voilà un petit code (Python 2.7) qui a l'air de faire ça.

    Paramètres:

    Le fichier à décomposer s'appelle ici nfc = 'ficid.txt' (on peut lui donner n'importe quel autre nom)

    Les fichiers créés se trouveront dans le sous-répertoire srep = 'srep', et auront comme nom, par exemple: "4500099.txt" pour le 99ème fichier de l'ID="45".

    Le sous-répertoire 'srep' doit être vide: il est donc vidé en début d'exécution.

    Les 2 dictionnaires sur lesquels s'appuie la logique sont:

    didf qui contient, pour tous les fichiers déjà enregistrés sur disque, la correspondance ID:derniernuméro. Par exemple: si 4500099.txt est le dernier fichier enregistré pour l'ID='45', le dictionnaire contiendra: '45':'00099'.

    dido qui contient dans une liste pour chaque ID toutes les lignes déjà trouvées pour cet ID. A partir de la 10ème ligne, le fichier sera écrit et la clé ID détruite. Par exemple pour l'ID='45' à la 3ème ligne trouvée, on aura: '45':[ligne1, ligne2, ligne3].

    Le code est documenté:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import division
    # Python 2.7
     
    import sys, os
     
    nfc = 'ficid.txt'
    srep = 'srep'
     
    # effacement des fichiers du sous-répertoire srep s'il y en a
    import glob
    for nf in glob.iglob(os.path.join(srep, "[0-9][0-9]*.txt")):
        os.remove(nf)
     
    # garde le numéro du  dernier fichier enregistré pour chaque id
    # exemple: didf = {'45': '00007'} => dernier fichier: 4500007.txt
    didf = {} 
     
    # accumule les lignes (10 maxi) dans la liste liée à la clé 'ID'
    # exemple: dido = {'45': ['45XXX', '45YYY', ..., '45ZZZ']}
    dido = {}
     
    with open(nfc, 'r') as fr:
        for ligne in fr:
     
            # ID = les 2 premiers caractères de la ligne
            id = ligne[:2]
     
            # voir si on a déjà rencontré l'ID
            if not id in dido:
                dido[id] = [] # non: créer la liste vide
     
            # on ajoute la ligne à la liste
            dido[id].append(ligne)
     
            # enregistrement sur disque si la liste est pleine
            if len(dido[id])==10:
                # oui, la liste est pleine 
     
                # on détermine le numéro à partir du précédent numéro enregistré
                if id in didf:
                    num = "%0.5d" % (int(didf[id])+1,)
                else:
                    num = "00001" # l'ID n'existe pas encore: on commence à 00001
     
                # on enregistre le nouveau fichier avec les lignes de la liste
                nf = os.path.join(srep, id+num+'.txt')
                with open(nf, 'w') as fw:
                    for elem in dido[id]:
                        fw.write(elem)            
                # on met à jour le dernier numéro enregistré pour l'ID
                didf[id] = num
                # et on détruit la liste qu'on vient d'enregistrer sur disque
                dido.pop(id)
     
    # il faut enregistrer les derniers fichiers incomplets
    for id in dido:
     
            # on détermine le numéro à partir du précédent numéro enregistré
            if id in didf:
                num = "%0.5d" % (int(didf[id])+1,)
            else:
                num = "00001"
     
            # on enregistre le nouveau fichier avec les lignes de la liste
            nf = os.path.join(srep, id+num+'.txt')
            with open(nf, 'w') as fw:
                for elem in dido[id]:
                    fw.write(elem)
    J'ai essayé sur un fichier d'un million de lignes avec des ID=de '00' à '99' choisis au hasard: ça a été assez rapide (environ 3 minutes), mais il faut avoir conscience que ça fabrique alors environ 100.000 fichiers! (environ 1000 fichiers par ID). Il faudrait être sûr qu'un tel découpage procure un avantage quelconque sur la rapidité d'un traitement...

  5. #5
    Membre averti
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Mars 2011
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en Business Intelligence
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2011
    Messages : 39
    Par défaut
    Désolé de ne pas être très rapide, j'ai pas mal de taff.

    Alors j'ai regardé ton code c'est bien mais je n'arrive pas à l'utiliser car la même erreur revient tout le temps :

    SyntaxError: ('invalid syntax', ('<string>', 24, 6, "with open(nfc, 'r') as fr:"))

    Je pense que cette erreur est du au contenue de la variable nfc, dans ce cas à moi de mettre le bon chemin mais à tout hasard tu es sur de ta syntaxe sur cette ligne ?

    De plus mon besoin un peu plus simple, à partir du gros fichier txt source je n'ai pas besoin de plusieurs fichiers mais d'un seul. je veux juste alléger le fichier. Mais au pire j'adapterai ton code ce point la n'est pas très grave.

    Merci à toi

  6. #6
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    Quelle version de python utilises-tu ?

    with n'apparaît qu'à la version 2.5

Discussions similaires

  1. Réponses: 10
    Dernier message: 27/02/2006, 16h55
  2. [fstream] Manipulation d'un fichier ...
    Par Zenol dans le forum SL & STL
    Réponses: 6
    Dernier message: 11/02/2006, 10h49
  3. manipulation d'un fichier indexé par un arbre b
    Par nemya_1 dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 21/01/2006, 19h30
  4. Chargement fichier volumineux
    Par kirsoul dans le forum Installation
    Réponses: 2
    Dernier message: 26/07/2005, 14h53
  5. Réponses: 4
    Dernier message: 31/07/2004, 11h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo