Comment aurais-je pu mieux faire

Comment aurais-je pu mieux faire - Python - Programmation

Marsh Posté le 09-03-2011 à 15:44:12    

Salut à tous,
 
je débute en python, je m'en sert pour faire des petites conneries, genre opérations répétitives sur des fichiers, manipulation de texte, etc.
 
Récemment, j'ai du faire un script qui allait chercher deux dossier dans un chemin donné en ligne de commande, récupère la liste des fichiers dans chacun de ces deux dossiers, puis crée un fichier texte qui va contenir les deux listes entrelacées.
 
J'ai pas vraiment de probleme, dans la mesure ou ca marche, mais je voulais savoir si il y avait un moyen plus succint et plus élégant de faire comme j'ai fait.
 

Code :
  1. import glob
  2. import sys
  3.  
  4. if len(sys.argv) < 2 :
  5.  print "Entrer un chemin vers un dossier"
  6.  exit
  7.  
  8. flux = open(sys.argv[1]+'/image_list.txt', 'w')
  9. listG = glob.glob(sys.argv[1]+'/imageG/*')
  10. listD = glob.glob(sys.argv[1]+'/imageB/*')
  11.  
  12. if len(listD != len(listG):
  13.  print "Pas le meme nombre de fichier dans les deux dossiers"
  14.  exit
  15.  
  16. range = range(len(listG))
  17. range.pop()
  18.  
  19. for i in range:
  20.  flux.write(listG[i])
  21.  flux.write("\n" )
  22.  flux.write(listD[i])
  23.  flux.write("\n" )
  24. flux.close()


Message édité par snafu8 le 10-03-2011 à 18:53:59
Reply

Marsh Posté le 09-03-2011 à 15:44:12   

Reply

Marsh Posté le 10-03-2011 à 18:54:52    

Serieusement les gens, je vous donne a tous une occasion sans pareil de faire étalage de vos connaissance et pas une réponse? J'ai pas pondu la solution optimale du premier coup quand meme?

Reply

Marsh Posté le 10-03-2011 à 20:03:22    

Citation :

Comment aurais-je pu mieux faire

En n'oubliant pas une parenthèse?
if len(listD) != len(listG):
 :whistle:  
 
flux = open(sys.argv[1]+'/image_list.txt', 'w')
c'est mal placé, il faut plutôt le mettre après le test if len(listD)!= len(listG): car si tu quittes sur ce test, inutile d'avoir ouvert en écriture.
 
Bon, si j'avais eu à le faire en perl, j'aurais procédé ainsi:
 

Code :
  1. #!/usr/local/bin/perl
  2. use strict;
  3. use warnings;
  4. use File::Glob ':glob';
  5. use Maptastic  ':perly';
  6.  
  7. @ARGV or die "Entrer un chemin vers un dossier\n";
  8. (-d $ARGV[0]) or die "$! $ARGV[0]\n";
  9. (-d $ARGV[0].'/imageG/') or die "$! $ARGV[0]/imageG/\n";
  10. (-d $ARGV[0].'/imageB/') or die "$! $ARGV[0]/imageB/\n";
  11.  
  12. my @g = bsd_glob($ARGV[0].'/imageG/*', GLOB_QUOTE);
  13. my @b = bsd_glob($ARGV[0].'/imageB/*', GLOB_QUOTE);
  14. (@g == @b) or die "Pas le meme nombre de fichier dans les deux dossiers\n";
  15.  
  16. open(my $fh, '>', $ARGV[0].'/image_list.txt') or die "$! $ARGV[0]/image_list.txt\n";
  17. map_foreach {print $fh join("\n", @_), "\n"} \@g, \@b;
  18. # ou bien si on veut tout écrire d'un coup mais ca bouffe plus de mémoire
  19. # print $fh join("\n", map_shift {@_} \@g, \@b), "\n";
  20. close($fh);


Je ne sais pas pour python, mais le glob de base de perl n'aime pas les blancs dans les paths, d'ou le recours à bsd_glob et le flag GLOB_QUOTE.
A+,


Message édité par gilou le 11-03-2011 à 01:00:07

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 28-03-2011 à 10:53:00    

Bonjour,
 
Et ça sert à quoi d'avoir des listes entrelacées ? Es tu sûr que les fichiers se correspondent s'il y en a le même nombre, que leur tri est le même ?

Reply

Marsh Posté le 01-04-2011 à 22:09:33    

listdir pour le contenu d'un dossier, pas besoin de sortir glob pour un truc pareil
izip + chain.from_iterable l'entrelac
en python, les chemins ne se join pas à la main, prière d'utiliser os.path.join

 
Code :
  1. import functools, sys, os, itertools
  2. path_to = functools.partial(os.path.join, sys.argv[1])
  3.  
  4. list1 = os.listdir(path_to('imageG'))
  5. list2 = os.listdir(path_to('imageB'))
  6.  
  7. assert len(list1) == len(list2)
  8.  
  9. with open(path_to('list.txt'), 'wb') as out:
  10.    for filename in itertools.chain.from_iterable(itertools.izip(list1, list2)):
  11.        out.write(filename + '\n')
 

Si on veut éviter que ce ne soit lisible, je recommande d'y aller à coup de writelines ou de join par dessus, et en laissant le refcount CPython s'occuper du fichier:

Code :
  1. import functools, sys, os, itertools
  2. path_to = functools.partial(os.path.join, sys.argv[1])
  3.  
  4. list1 = os.listdir(path_to('imageG'))
  5. list2 = os.listdir(path_to('imageB'))
  6.  
  7. assert len(list1) == len(list2)
  8.  
  9. open(path_to('list.txt'), 'wb').write(
  10.    '\n'.join(itertools.chain.from_iterable(itertools.izip(list1, list2))))
 

Mais bon, sur ce genre d'utilities j'aurais tendance à sortir directement sur stdout et à piper depuis le shell.

Code :
  1. import functools, sys, os, itertools
  2. path_to = functools.partial(os.path.join, sys.argv[1])
  3.  
  4. list1 = os.listdir(path_to('imageG'))
  5. list2 = os.listdir(path_to('imageB'))
  6.  
  7. if len(list1) != len(list2): sys.exit(1)
  8.  
  9. for filename in itertools.chain.from_iterable(itertools.izip(list1, list2)):
  10.    print(filename)


Message édité par masklinn le 01-04-2011 à 22:17:44

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed