|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Bonjour, j'ai besoin de transformer en format csv délimité, des
fichiers fixes. Le problème c'est que ces fichiers peuvent être très gros, plusieurs millions de lignes et plusieurs milliers de caractères par ligne. J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense pourrait être bien optimisé. Merci d'avance pour vos suggestions. ========= # _*_ coding: utf8 _*_ #!/usr/bin/env python # Auteur : Philippe Lotton # Date de création: import sys import datetime if __name__ == '__main__': args = sys.argv[1:] if len(args) == 2: # 2 paramètres obligatoires fic_entree = args[0] # Fichier source fic_format = args[1] #Fichier format else: print '''Vous devez passez 2 arguments, le fichier source et le fichier paramètre ex: csv.py MonFic.txt MonFormat.txt Le fichier source doit avoir des enregistrements de longueurs fixes. Le fichier format doit ètre de la forme: position , longueur <rc>, autant de ligne que de champs dans le fichier source. ''' exit() print datetime.datetime.now().time() fic_param = open('format.txt', "r") # Lecture du fichier paramètre format = fic_param.readlines() # Création tableaux des paramètres fic_param.close() fic_out = open('csv.txt', 'w') #Ouverture fichier de sortie fic_source = open(fic_entree, 'r') # Lecture du fichier source while 1: # ligne_source = fic_source.readline() if ligne_source =='': break else : ligne_cible = '' # Ligne de sortie écrite dans le fichier for j in format: params = j.split(',') #Création d'un tableau de paramètres pos1 = int(params[0])-1 #Position 1 pos2 = pos1 + int(params[1]) #Position 2 temp = ligne_source[ pos1:pos2] ligne_cible = ligne_cible + temp + ',' # Concaténation ligne_cible = ligne_cible[0:-1] fic_out.write(ligne_cible + "\n") ligne_cible = '' fic_source.close() fic_out.close() print datetime.datetime.now().time() exit() |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
> Bonjour, j'ai besoin de transformer en format csv délimité, des > fichiers fixes. > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > millions de lignes et plusieurs milliers de caractères par ligne. > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > pourrait être bien optimisé. > Merci d'avance pour vos suggestions. > > ========= > # _*_ coding: utf8 _*_ > #!/usr/bin/env python > # Auteur : Philippe Lotton > # Date de création: > > import sys > import datetime C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais y a-t-il une raison pour laquelle vous n'utilisez pas le module standard csv ? Au début, je pensais que vous aviez écrit votre solution pour justement être plus performant mais en regardant le source de csv.py, je constate que celui-ci délègue la majorité du travail à un module et C. En fait si, c'est bien une suggestion d'optim après tout. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
> Bonjour, j'ai besoin de transformer en format csv délimité, des > fichiers fixes. > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > millions de lignes et plusieurs milliers de caractères par ligne. > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > pourrait être bien optimisé. > Merci d'avance pour vos suggestions. > > ========= > # _*_ coding: utf8 _*_ > #!/usr/bin/env python > # Auteur : Philippe Lotton > # Date de création: > > import sys > import datetime C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais y a-t-il une raison pour laquelle vous n'utilisez pas le module standard csv ? Au début, je pensais que vous aviez écrit votre solution pour justement être plus performant mais en regardant le source de csv.py, je constate que celui-ci délègue la majorité du travail à un module et C. En fait si, c'est bien une suggestion d'optim après tout. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
> Bonjour, j'ai besoin de transformer en format csv délimité, des > fichiers fixes. > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > millions de lignes et plusieurs milliers de caractères par ligne. > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > pourrait être bien optimisé. > Merci d'avance pour vos suggestions. > > ========= > # _*_ coding: utf8 _*_ > #!/usr/bin/env python > # Auteur : Philippe Lotton > # Date de création: > > import sys > import datetime > if __name__ == '__main__': Déjà, découpe ton code en fonctions. > args = sys.argv[1:] > if len(args) == 2: # 2 paramètres obligatoires > fic_entree = args[0] # Fichier source > fic_format = args[1] #Fichier format > else: > print '''Vous devez passez 2 arguments, le fichier source et > le fichier paramètre > ex: csv.py MonFic.txt MonFormat.txt > Le fichier source doit avoir des enregistrements de longueurs > fixes. > Le fichier format doit ètre de la forme: position , longueur > <rc>, > autant de ligne que de champs dans le fichier source. > ''' les messages d'erreurs devraient aller sur la sortie d'erreur, pas sur la sortie standard. Donc, print >> sys.stderr. Ceci étant, puisque sys.exit(msg) écrit le message sur stderr, tu peux tout simplement passer ton message à sys.exit(). > exit() > print datetime.datetime.now().time() > fic_param = open('format.txt', "r") # Lecture du fichier > paramètre Pas la peine de commenter chaque ligne avec une paraphrase du code. On est capable de lire le code. Si ton commentaire n'apporte rien, ne commente pas. Accessoirement, je suppose que tu veux: fic_param = open(fic_format) Et là, il apparaît que tu utilises la même convention de nommage pour des chemins de fichier et des objets fichier. Combien de temps avant que tu ne t'embrouilles, à ton avis ? > format = fic_param.readlines() > fic_param.close() > > fic_out = open('csv.txt', 'w') > fic_source = open(fic_entree, 'r') > while 1: > ligne_source = fic_source.readline() > if ligne_source =='': > break > else : Les fichiers en lecture sont leur propre itérateur. Ca t'évite un test, au passage... for ligne_source in fic_source: > ligne_cible = '' # Ligne de sortie écrite dans > le fichier > for j in format: > params = j.split(',') #Création d'un > tableau de paramètres > pos1 = int(params[0])-1 #Position 1 > pos2 = pos1 + int(params[1]) #Position 2 T'a pas l'impression que refaire ces calculs à chaque ligne du fichier source est une perte de temps phénoménale ? Parse le tout avant d'entrer dans la boucle, tu gagnera du temps. > temp = ligne_source[ pos1:pos2] > ligne_cible = ligne_cible + temp + ',' # > Concaténation A éviter, tout particulièrement sous cette forme (la forme 'ligne += truc' est optimisée dans les versions récentes de CPython, mais ça reste une mauvaise solution). La bonne façon de faire est de stocker les champs dans une liste, et faire un ",".join(laliste) à la fin. > ligne_cible = ligne_cible[0:-1] ce qui évite aussi ça... > fic_out.write(ligne_cible + "\n") > ligne_cible = '' cette dernière instruction est inutile, tu le fais déjà au début de la boucle. > fic_source.close() > fic_out.close() > print datetime.datetime.now().time() > exit() > Correction possible, mais Q&D et pas très robuste. J'ai gardé ton nommage mais tu devrais le corriger. NB : pas testé. import sys import datetime def parse_params(lines): params = [] for line in enumerate(lines): line = line.strip() if not line: continue parts = line.split(',') pos1 = int(parts[0])-1 pos2 = pos1 + int(parts[1]) params.append(slice(pos1, pos2)) return params def do_import(params, fic_source, fic_out): write = fic_out.write sep = ',' join = sep.join # evite un lookup for ligne_source in fic_source: ligne_cible = [ligne_source[slice] for slice in params] write(join(ligne_cible) + "\n") def main(args): try: fic_entree, fic_format = args except ValueError: sys.exit('''Vous devez passez 2 arguments, le fichier source et le fichier paramètre ex: csv.py MonFic.txt MonFormat.txt Le fichier source doit avoir des enregistrements de longueurs fixes. Le fichier format doit ètre de la forme: position , longueur <rc>, autant de ligne que de champs dans le fichier source. ''') # XXX : gérer le cas d'une exception durant le parsing fic_param = open(fic_format) params = parse_param(fic_param) fic_params.close() # XXX : gérer le cas d'une erreur lors de l'ouverture de fic_out fic_source = open(fic_entree, 'r') fic_out = open('csv.txt', 'w') try: do_import(params, fic_source, fic_out) finally: fic_source.close() fic_out.close() if __name__ == '__main__': print >> sys.stderr, datetime.datetime.now().time() main(sys.argv[1:]) print >> sys.stderr, datetime.datetime.now().time() HTH |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
> Bonjour, j'ai besoin de transformer en format csv délimité, des > fichiers fixes. > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > millions de lignes et plusieurs milliers de caractères par ligne. > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > pourrait être bien optimisé. > Merci d'avance pour vos suggestions. > > ========= > # _*_ coding: utf8 _*_ > #!/usr/bin/env python > # Auteur : Philippe Lotton > # Date de création: > > import sys > import datetime > if __name__ == '__main__': Déjà, découpe ton code en fonctions. > args = sys.argv[1:] > if len(args) == 2: # 2 paramètres obligatoires > fic_entree = args[0] # Fichier source > fic_format = args[1] #Fichier format > else: > print '''Vous devez passez 2 arguments, le fichier source et > le fichier paramètre > ex: csv.py MonFic.txt MonFormat.txt > Le fichier source doit avoir des enregistrements de longueurs > fixes. > Le fichier format doit ètre de la forme: position , longueur > <rc>, > autant de ligne que de champs dans le fichier source. > ''' les messages d'erreurs devraient aller sur la sortie d'erreur, pas sur la sortie standard. Donc, print >> sys.stderr. Ceci étant, puisque sys.exit(msg) écrit le message sur stderr, tu peux tout simplement passer ton message à sys.exit(). > exit() > print datetime.datetime.now().time() > fic_param = open('format.txt', "r") # Lecture du fichier > paramètre Pas la peine de commenter chaque ligne avec une paraphrase du code. On est capable de lire le code. Si ton commentaire n'apporte rien, ne commente pas. Accessoirement, je suppose que tu veux: fic_param = open(fic_format) Et là, il apparaît que tu utilises la même convention de nommage pour des chemins de fichier et des objets fichier. Combien de temps avant que tu ne t'embrouilles, à ton avis ? > format = fic_param.readlines() > fic_param.close() > > fic_out = open('csv.txt', 'w') > fic_source = open(fic_entree, 'r') > while 1: > ligne_source = fic_source.readline() > if ligne_source =='': > break > else : Les fichiers en lecture sont leur propre itérateur. Ca t'évite un test, au passage... for ligne_source in fic_source: > ligne_cible = '' # Ligne de sortie écrite dans > le fichier > for j in format: > params = j.split(',') #Création d'un > tableau de paramètres > pos1 = int(params[0])-1 #Position 1 > pos2 = pos1 + int(params[1]) #Position 2 T'a pas l'impression que refaire ces calculs à chaque ligne du fichier source est une perte de temps phénoménale ? Parse le tout avant d'entrer dans la boucle, tu gagnera du temps. > temp = ligne_source[ pos1:pos2] > ligne_cible = ligne_cible + temp + ',' # > Concaténation A éviter, tout particulièrement sous cette forme (la forme 'ligne += truc' est optimisée dans les versions récentes de CPython, mais ça reste une mauvaise solution). La bonne façon de faire est de stocker les champs dans une liste, et faire un ",".join(laliste) à la fin. > ligne_cible = ligne_cible[0:-1] ce qui évite aussi ça... > fic_out.write(ligne_cible + "\n") > ligne_cible = '' cette dernière instruction est inutile, tu le fais déjà au début de la boucle. > fic_source.close() > fic_out.close() > print datetime.datetime.now().time() > exit() > Correction possible, mais Q&D et pas très robuste. J'ai gardé ton nommage mais tu devrais le corriger. NB : pas testé. import sys import datetime def parse_params(lines): params = [] for line in enumerate(lines): line = line.strip() if not line: continue parts = line.split(',') pos1 = int(parts[0])-1 pos2 = pos1 + int(parts[1]) params.append(slice(pos1, pos2)) return params def do_import(params, fic_source, fic_out): write = fic_out.write sep = ',' join = sep.join # evite un lookup for ligne_source in fic_source: ligne_cible = [ligne_source[slice] for slice in params] write(join(ligne_cible) + "\n") def main(args): try: fic_entree, fic_format = args except ValueError: sys.exit('''Vous devez passez 2 arguments, le fichier source et le fichier paramètre ex: csv.py MonFic.txt MonFormat.txt Le fichier source doit avoir des enregistrements de longueurs fixes. Le fichier format doit ètre de la forme: position , longueur <rc>, autant de ligne que de champs dans le fichier source. ''') # XXX : gérer le cas d'une exception durant le parsing fic_param = open(fic_format) params = parse_param(fic_param) fic_params.close() # XXX : gérer le cas d'une erreur lors de l'ouverture de fic_out fic_source = open(fic_entree, 'r') fic_out = open('csv.txt', 'w') try: do_import(params, fic_source, fic_out) finally: fic_source.close() fic_out.close() if __name__ == '__main__': print >> sys.stderr, datetime.datetime.now().time() main(sys.argv[1:]) print >> sys.stderr, datetime.datetime.now().time() HTH |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit :
> pil91 a écrit : >> Bonjour, j'ai besoin de transformer en format csv délimité, des >> fichiers fixes. (snip) > C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais y > a-t-il une raison pour laquelle vous n'utilisez pas le module standard > csv ? Peut-être le fait que le format csv soit la cible, pas la source ?-) |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit :
> pil91 a écrit : >> Bonjour, j'ai besoin de transformer en format csv délimité, des >> fichiers fixes. (snip) > C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais y > a-t-il une raison pour laquelle vous n'utilisez pas le module standard > csv ? Peut-être le fait que le format csv soit la cible, pas la source ?-) |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Bruno Desthuilliers a écrit :
> Christophe a écrit : >> pil91 a écrit : >>> Bonjour, j'ai besoin de transformer en format csv délimité, des >>> fichiers fixes. > (snip) > >> C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais >> y a-t-il une raison pour laquelle vous n'utilisez pas le module >> standard csv ? > > Peut-être le fait que le format csv soit la cible, pas la source ?-) Et ? Le module csv fait lecture et écriture. on module csv: NAME csv - CSV parsing and writing. FILE c:\python25\lib\csv.py DESCRIPTION This module provides classes that assist in the reading and writing of Comma Separated Value (CSV) files, and implements the interface (...) |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
Bruno Desthuilliers a écrit :
> Christophe a écrit : >> pil91 a écrit : >>> Bonjour, j'ai besoin de transformer en format csv délimité, des >>> fichiers fixes. > (snip) > >> C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais >> y a-t-il une raison pour laquelle vous n'utilisez pas le module >> standard csv ? > > Peut-être le fait que le format csv soit la cible, pas la source ?-) Et ? Le module csv fait lecture et écriture. on module csv: NAME csv - CSV parsing and writing. FILE c:\python25\lib\csv.py DESCRIPTION This module provides classes that assist in the reading and writing of Comma Separated Value (CSV) files, and implements the interface (...) |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
On 10 sep, 17:03, Christophe <chris.cavala...@free.fr> wrote:
> pil91 a écrit : > > > > > Bonjour, j'ai besoin de transformer en format csv délimité, des > > fichiers fixes. > > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > > millions de lignes et plusieurs milliers de caractères par ligne. > > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > > pourrait être bien optimisé. > > Merci d'avance pour vos suggestions. > > > ========= > > # _*_ coding: utf8 _*_ > > #!/usr/bin/env python > > # Auteur : Philippe Lotton > > # Date de création: > > > import sys > > import datetime > > C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais y > a-t-il une raison pour laquelle vous n'utilisez pas le module standard > csv ? Au début, je pensais que vous aviez écrit votre solution pour > justement être plus performant mais en regardant le source de csv.py, je > constate que celui-ci délègue la majorité du travail à un module et C. > > En fait si, c'est bien une suggestion d'optim après tout. Je pensais améliorer les choses en remplacant la concaténation de ma chaine un append dans un tableau, puis un join ---- else : sortie = [] for j in format: params = j.split(',') #Création d'un tableau de paramètres pos1 = int(params[0])-1 #Position 1 pos2 = pos1 + int(params[1]) #Position 2 temp = ligne_source[ pos1:pos2] sortie.append(temp) result = ','.join(sortie) out.write(result + "\n") sortie = [] fic_source.close() out.close() --- Excès d'autosatisfaction, c'est quif quif, 18s, sur 1 000 000 d'enregistrement avec cette structure ------ aaaaaaaaaaabbbbwyyyyyyyyyyyyyyy tttttttttttppppbqqqqqqqqqqqqqqq rrrrrrrrrrrhhhhkeeeeeeeeeeeeeee ------- @Christophe Oui c'est vrai le module csv, ben... j'ai essayé de l'importer et puis après je suis passé à autre chose. Quand je lancais l'exécution j'obtenais un message 'module object has no attribute reader. |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
On 10 sep, 17:03, Christophe <chris.cavala...@free.fr> wrote:
> pil91 a écrit : > > > > > Bonjour, j'ai besoin de transformer en format csv délimité, des > > fichiers fixes. > > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > > millions de lignes et plusieurs milliers de caractères par ligne. > > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > > pourrait être bien optimisé. > > Merci d'avance pour vos suggestions. > > > ========= > > # _*_ coding: utf8 _*_ > > #!/usr/bin/env python > > # Auteur : Philippe Lotton > > # Date de création: > > > import sys > > import datetime > > C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais y > a-t-il une raison pour laquelle vous n'utilisez pas le module standard > csv ? Au début, je pensais que vous aviez écrit votre solution pour > justement être plus performant mais en regardant le source de csv.py, je > constate que celui-ci délègue la majorité du travail à un module et C. > > En fait si, c'est bien une suggestion d'optim après tout. Je pensais améliorer les choses en remplacant la concaténation de ma chaine un append dans un tableau, puis un join ---- else : sortie = [] for j in format: params = j.split(',') #Création d'un tableau de paramètres pos1 = int(params[0])-1 #Position 1 pos2 = pos1 + int(params[1]) #Position 2 temp = ligne_source[ pos1:pos2] sortie.append(temp) result = ','.join(sortie) out.write(result + "\n") sortie = [] fic_source.close() out.close() --- Excès d'autosatisfaction, c'est quif quif, 18s, sur 1 000 000 d'enregistrement avec cette structure ------ aaaaaaaaaaabbbbwyyyyyyyyyyyyyyy tttttttttttppppbqqqqqqqqqqqqqqq rrrrrrrrrrrhhhhkeeeeeeeeeeeeeee ------- @Christophe Oui c'est vrai le module csv, ben... j'ai essayé de l'importer et puis après je suis passé à autre chose. Quand je lancais l'exécution j'obtenais un message 'module object has no attribute reader. |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit :
> Bruno Desthuilliers a écrit : >> Christophe a écrit : >>> Bruno Desthuilliers a écrit : >>>> Christophe a écrit : >>>>> pil91 a écrit : >>>>>> Bonjour, j'ai besoin de transformer en format csv délimité, des >>>>>> fichiers fixes. >>>> (snip) >>>> >>>>> C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) >>>>> mais y a-t-il une raison pour laquelle vous n'utilisez pas le >>>>> module standard csv ? >>>> >>>> Peut-être le fait que le format csv soit la cible, pas la source ?-) >>> >>> Et ? Le module csv fait lecture et écriture. >> >> Oui. Il lit effectivement des csv. Ce qui n'est pas le cas des >> fichiers sources de l'OP, ni la source de son problème. > > > Ah, je m'excuse, j'avais mal vu l'énoncé et je confondais le format du > fichier de format avec le format du fichier d'entrée de données. Comme > quoi il est mal de répondre à ce genre de questions pendant les heures > de travail (même pendant une pause) : on va trop vite et on rate des > choses importantes ![]() Pas de blème, ça arrive à tout le monde (moi le premier...) !-) |
|
|
|
#13 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit :
> Bruno Desthuilliers a écrit : >> Christophe a écrit : >>> Bruno Desthuilliers a écrit : >>>> Christophe a écrit : >>>>> pil91 a écrit : >>>>>> Bonjour, j'ai besoin de transformer en format csv délimité, des >>>>>> fichiers fixes. >>>> (snip) >>>> >>>>> C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) >>>>> mais y a-t-il une raison pour laquelle vous n'utilisez pas le >>>>> module standard csv ? >>>> >>>> Peut-être le fait que le format csv soit la cible, pas la source ?-) >>> >>> Et ? Le module csv fait lecture et écriture. >> >> Oui. Il lit effectivement des csv. Ce qui n'est pas le cas des >> fichiers sources de l'OP, ni la source de son problème. > > > Ah, je m'excuse, j'avais mal vu l'énoncé et je confondais le format du > fichier de format avec le format du fichier d'entrée de données. Comme > quoi il est mal de répondre à ce genre de questions pendant les heures > de travail (même pendant une pause) : on va trop vite et on rate des > choses importantes ![]() Pas de blème, ça arrive à tout le monde (moi le premier...) !-) |
|
|
|
#14 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
> @Christophe > Oui c'est vrai le module csv, ben... j'ai essayé de l'importer et puis > après je suis passé à autre chose. > Quand je lancais l'exécution j'obtenais un message 'module object has > no attribute reader. Ah mais chez moi il marche très bien Si le module était cassé à cepoint, ça se saurait. Allez, je parie qu'il y a un petit fichier csv.py ou csv.pyc qui traine pas loin et qui cache le module officiel. |
|
|
|
#15 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
> @Christophe > Oui c'est vrai le module csv, ben... j'ai essayé de l'importer et puis > après je suis passé à autre chose. > Quand je lancais l'exécution j'obtenais un message 'module object has > no attribute reader. Ah mais chez moi il marche très bien Si le module était cassé à cepoint, ça se saurait. Allez, je parie qu'il y a un petit fichier csv.py ou csv.pyc qui traine pas loin et qui cache le module officiel. |
|
|
|
#16 |
|
Messages: n/a
Hébergeur: |
On 10 sep, 17:31, pil91 <philippe.lot...@gmail.com> wrote:
> On 10 sep, 17:03, Christophe <chris.cavala...@free.fr> wrote: > > > > > pil91 a écrit : > > > > Bonjour, j'ai besoin de transformer en format csv délimité, des > > > fichiers fixes. > > > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > > > millions de lignes et plusieurs milliers de caractères par ligne. > > > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > > > pourrait être bien optimisé. > > > Merci d'avance pour vos suggestions. > > > > ========= > > > # _*_ coding: utf8 _*_ > > > #!/usr/bin/env python > > > # Auteur : Philippe Lotton > > > # Date de création: > > > > import sys > > > import datetime > > > C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) maisy > > a-t-il une raison pour laquelle vous n'utilisez pas le module standard > > csv ? Au début, je pensais que vous aviez écrit votre solution pour > > justement être plus performant mais en regardant le source de csv.py,je > > constate que celui-ci délègue la majorité du travail à un module et C. > > > En fait si, c'est bien une suggestion d'optim après tout. > > Je pensais améliorer les choses en remplacant la concaténation de ma > chaine un append dans un tableau, puis un join > ---- > else : > sortie = [] > for j in format: > params = j.split(',') #Création d'un > tableau de paramètres > pos1 = int(params[0])-1 #Position 1 > pos2 = pos1 + int(params[1]) #Position 2 > temp = ligne_source[ pos1:pos2] > sortie.append(temp) > result = ','.join(sortie) > out.write(result + "\n") > sortie = [] > fic_source.close() > out.close() > --- > Excès d'autosatisfaction, c'est quif quif, 18s, sur 1 000 000 > d'enregistrement avec cette structure > ------ > aaaaaaaaaaabbbbwyyyyyyyyyyyyyyy > tttttttttttppppbqqqqqqqqqqqqqqq > rrrrrrrrrrrhhhhkeeeeeeeeeeeeeee > ------- > @Christophe > Oui c'est vrai le module csv, ben... j'ai essayé de l'importer et puis > après je suis passé à autre chose. > Quand je lancais l'exécution j'obtenais un message 'module object has > no attribute reader. @Bruno Desthuilliers Merci pour ce cours magistral, je revois ma copie demain .Effectivement l'utilisation du module csv serait plus orthodoxe et efficace. |
|
|
|
#17 |
|
Messages: n/a
Hébergeur: |
On 10 sep, 17:31, pil91 <philippe.lot...@gmail.com> wrote:
> On 10 sep, 17:03, Christophe <chris.cavala...@free.fr> wrote: > > > > > pil91 a écrit : > > > > Bonjour, j'ai besoin de transformer en format csv délimité, des > > > fichiers fixes. > > > Le problème c'est que ces fichiers peuvent être très gros, plusieurs > > > millions de lignes et plusieurs milliers de caractères par ligne. > > > J'ai donc écrit ce code sous windows en Python 2.5.2, qui, je pense > > > pourrait être bien optimisé. > > > Merci d'avance pour vos suggestions. > > > > ========= > > > # _*_ coding: utf8 _*_ > > > #!/usr/bin/env python > > > # Auteur : Philippe Lotton > > > # Date de création: > > > > import sys > > > import datetime > > > C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) maisy > > a-t-il une raison pour laquelle vous n'utilisez pas le module standard > > csv ? Au début, je pensais que vous aviez écrit votre solution pour > > justement être plus performant mais en regardant le source de csv.py,je > > constate que celui-ci délègue la majorité du travail à un module et C. > > > En fait si, c'est bien une suggestion d'optim après tout. > > Je pensais améliorer les choses en remplacant la concaténation de ma > chaine un append dans un tableau, puis un join > ---- > else : > sortie = [] > for j in format: > params = j.split(',') #Création d'un > tableau de paramètres > pos1 = int(params[0])-1 #Position 1 > pos2 = pos1 + int(params[1]) #Position 2 > temp = ligne_source[ pos1:pos2] > sortie.append(temp) > result = ','.join(sortie) > out.write(result + "\n") > sortie = [] > fic_source.close() > out.close() > --- > Excès d'autosatisfaction, c'est quif quif, 18s, sur 1 000 000 > d'enregistrement avec cette structure > ------ > aaaaaaaaaaabbbbwyyyyyyyyyyyyyyy > tttttttttttppppbqqqqqqqqqqqqqqq > rrrrrrrrrrrhhhhkeeeeeeeeeeeeeee > ------- > @Christophe > Oui c'est vrai le module csv, ben... j'ai essayé de l'importer et puis > après je suis passé à autre chose. > Quand je lancais l'exécution j'obtenais un message 'module object has > no attribute reader. @Bruno Desthuilliers Merci pour ce cours magistral, je revois ma copie demain .Effectivement l'utilisation du module csv serait plus orthodoxe et efficace. |
|
|
|
#18 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit :
> Bruno Desthuilliers a écrit : >> Christophe a écrit : >>> pil91 a écrit : >>>> Bonjour, j'ai besoin de transformer en format csv délimité, des >>>> fichiers fixes. >> (snip) >> >>> C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais >>> y a-t-il une raison pour laquelle vous n'utilisez pas le module >>> standard csv ? >> >> Peut-être le fait que le format csv soit la cible, pas la source ?-) > > Et ? Le module csv fait lecture et écriture. Oui. Il lit effectivement des csv. Ce qui n'est pas le cas des fichiers sources de l'OP, ni la source de son problème. > > > on module csv: > > NAME > csv - CSV parsing and writing. > > FILE > c:\python25\lib\csv.py > > DESCRIPTION > This module provides classes that assist in the reading and writing > of Comma Separated Value (CSV) files, and implements the interface > (...) Merci, c'est gentil, je ne l'utilise qu'une cinquantaine de fois par an, ce module... |
|
|
|
#19 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit :
> Bruno Desthuilliers a écrit : >> Christophe a écrit : >>> pil91 a écrit : >>>> Bonjour, j'ai besoin de transformer en format csv délimité, des >>>> fichiers fixes. >> (snip) >> >>> C'est pas une suggestion d'optim (enfin, ça pourrait le devenir) mais >>> y a-t-il une raison pour laquelle vous n'utilisez pas le module >>> standard csv ? >> >> Peut-être le fait que le format csv soit la cible, pas la source ?-) > > Et ? Le module csv fait lecture et écriture. Oui. Il lit effectivement des csv. Ce qui n'est pas le cas des fichiers sources de l'OP, ni la source de son problème. > > > on module csv: > > NAME > csv - CSV parsing and writing. > > FILE > c:\python25\lib\csv.py > > DESCRIPTION > This module provides classes that assist in the reading and writing > of Comma Separated Value (CSV) files, and implements the interface > (...) Merci, c'est gentil, je ne l'utilise qu'une cinquantaine de fois par an, ce module... |
|
|
|
#20 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
(snip) > Effectivement l'utilisation du module csv serait plus orthodoxe et > efficace. Pour l'écriture, éventuellement, et encore seulement pour des trucs un peu complexes (quotes etc). Pour la lecture, je doute... Si j'ai bien compris, chaque ligne de ton fichier source est composé de X champs, chaque champ ayant une taille (fixe) differente. Si oui, ça n'a aucun rapport avec un format csv, donc... |
|
|
|
#21 |
|
Messages: n/a
Hébergeur: |
pil91 a écrit :
(snip) > Effectivement l'utilisation du module csv serait plus orthodoxe et > efficace. Pour l'écriture, éventuellement, et encore seulement pour des trucs un peu complexes (quotes etc). Pour la lecture, je doute... Si j'ai bien compris, chaque ligne de ton fichier source est composé de X champs, chaque champ ayant une taille (fixe) differente. Si oui, ça n'a aucun rapport avec un format csv, donc... |
|
|
|
#22 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit :
> pil91 a écrit : (snip) >> Je pensais améliorer les choses en remplacant la concaténation de ma >> chaine un append dans un tableau, puis un join > (...) >> Excès d'autosatisfaction, c'est quif quif, 18s, sur 1 000 000 >> d'enregistrement avec cette structure > > Ah oui, à ce sujet l'implémentation CPython optimise automatiquement les > longues suites de concaténations dans une même string de la façon dont > tu le fais. Plus ou moins... la version avec un assignement augmenté (s += xxx) est un poil plus rapide que celle avec un réassignement (s = s + xxx) Un petit bench valant mieux qu'un long discours: from timeit import Timer repeat = xrange(100000) def concat(): s = '' for i in repeat: s = s + 'aaaaa' def concat_aug(): s = '' for i in repeat: s += 'aaaaa' def append_join(): s = [] for i in repeat: s.append('aaaaa') s = ''.join(s) def local_append_join(): s = [] append = s.append for i in repeat: append('aaaaa') s = ''.join(s) def comp_join(): s = ''.join('aaaaa' for i in repeat) timers = [ (funcname, Timer('%s()' % funcname, 'from __main__ import %s' % funcname)) for funcname in ('concat', 'concat_aug', 'append_join', 'local_append_join', 'comp_join') ] for funcname, t in timers: print funcname, t.timeit(100) Résultats ici (python 2.5.1 sous gentoo-linux): concat 3.99100494385 concat_aug 3.96803593636 append_join 6.26043510437 local_append_join 3.67693090439 comp_join 3.72800898552 Le mauvais résultat de append_join par rapport à local_append_join s'explique par le hit dû au lookup de list.append, suivi de l'instanciation de l'objet méthode. Comme quoi cette simple optimisation (localiser les methodes appelées dans une boucle 'intensive') est très payante. Par contre, dans le cas de l'OP, je ne sais pas si ce sera vraiment plus intéressant (pour la boucle intérieure de do_import) dans la mesure où c'est, justement dans une boucle imbriquée. Mais bon, pil, tu peux tester les deux... AMHA, selon le jeu d'essai (données sources), tu aura des résultats en faveur tantôt de la solution local_append_join, tantôt en faveur de la solution comp_join. > Avec une version un peu plus ancienne de Python, tu aurais > certainement vu une très grande amélioration. Aucun doute.... |
|
|
|
#23 |
|
Messages: n/a
Hébergeur: |
Christophe a écrit : > pil91 a écrit : (snip) >> Je pensais améliorer les choses en remplacant la concaténation de ma >> chaine un append dans un tableau, puis un join > (...) >> Excès d'autosatisfaction, c'est quif quif, 18s, sur 1 000 000 >> d'enregistrement avec cette structure > > Ah oui, à ce sujet l'implémentation CPython optimise automatiquement les > longues suites de concaténations dans une même string de la façon dont > tu le fais. Plus ou moins... la version avec un assignement augmenté (s += xxx) est un poil plus rapide que celle avec un réassignement (s = s + xxx) Un petit bench valant mieux qu'un long discours: from timeit import Timer repeat = xrange(100000) def concat(): s = '' for i in repeat: s = s + 'aaaaa' def concat_aug(): s = '' for i in repeat: s += 'aaaaa' def append_join(): s = [] for i in repeat: s.append('aaaaa') s = ''.join(s) def local_append_join(): s = [] append = s.append for i in repeat: append('aaaaa') s = ''.join(s) def comp_join(): s = ''.join('aaaaa' for i in repeat) timers = [ (funcname, Timer('%s()' % funcname, 'from __main__ import %s' % funcname)) for funcname in ('concat', 'concat_aug', 'append_join', 'local_append_join', 'comp_join') ] for funcname, t in timers: print funcname, t.timeit(100) Résultats ici (python 2.5.1 sous gentoo-linux): concat 3.99100494385 concat_aug 3.96803593636 append_join 6.26043510437 local_append_join 3.67693090439 comp_join 3.72800898552 Le mauvais résultat de append_join par rapport à local_append_join s'explique par le hit dû au lookup de list.append, suivi de l'instanciation de l'objet méthode. Comme quoi cette simple optimisation (localiser les methodes appelées dans une boucle 'intensive') est très payante. Par contre, dans le cas de l'OP, je ne sais pas si ce |