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 :

Affichage ligne par ligne en temps réel d'un traitement long en console dans un processus [Python 3.X]


Sujet :

Python

  1. #1
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut Affichage ligne par ligne en temps réel d'un traitement long en console dans un processus
    Bonjour,

    J'aimerais automatiser avec un programme Python un traitement long qui se fait d'habitude en console. Il s'agit en fait d'une conversion de format video avec l'excellent ffmpeg, dont l'exécution peut demander plus de 10 minutes.

    J'essaie alors de lancer le programme et ses arguments dans un processus (avec subprocess.Popen), mais je dois attendre que le processus soit terminé pour avoir les lignes d'affichage, alors que je voudrais l'affichage progressif pendant le traitement. comme je les ai dans la console.

    J'ai cherché sur le web pendant des heures, et aucun exemple trouvé n'a permis cela: j'ai donc la console avec un écran noir pendant toute la durée du traitement.

    Voilà un petit exemple de code qui affiche l'aide de python (affichage rapide ici) avec Windows 10 et Python 3.4:

    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
    import sys, os
    import subprocess
     
    console = 'cmd /k'
     
    with subprocess.Popen(console, 
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE, 
                          stderr=subprocess.STDOUT, 
                          shell=True,
                          bufsize=10000) as proc:
     
        commande = br'E:\Python34\python.exe -h'
        lignes = str(proc.communicate(commande + b'\n')[0], 'cp850').splitlines()
        for ligne in lignes:
            print(ligne)
     
        x = input("?") # pour garder la console ouverte en fin du traitement
    Quelqu'un aurait-il une idée?
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  2. #2
    Expert éminent

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Pour traiter les retours de commande ligne par ligne je procède comme ceci:

    (Je copie tel quel)
    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
     
                self.proc = subprocess.Popen(["gphoto2", "--get-all-files"], 
                                            universal_newlines=True, 
                                            stdout=subprocess.PIPE)
     
                while 1:
                    text = self.proc.stdout.readline()[:-1]
                    if type(text) != str or text == '' and self.proc.poll() != None: 
                        break
     
                    elif type(text) == str and len(text) > 6:
                        self.fileDownloaded.emit(text)
     
                self.proc = None
                self.downloadingFinished.emit(r)
    Donc, ici, chaque étape du processus est contenue dans text moi je l'affiche dans une interface mais tu peux simplement le printer.

  3. #3
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2010
    Messages
    553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2010
    Messages : 553
    Points : 2 740
    Points
    2 740
    Par défaut
    Salut,

    une solution qui pourrait te convenir, c'est de faire en sorte que ton processus ouvert avec Popen écrive directement sur la sortie standard plutôt que dans un pipe. ainsi, tu lances juste tes commandes et leurs sorties arrivent toutes seules sur la console sans traitement spécifique.

    exemple testé en python 2.7, mais ça doit être transposable sans problème en python 3.4:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import sys
    import subprocess
    
    console = 'cmd /k'
    proc = subprocess.Popen(console, stdin=subprocess.PIPE,
                            stdout=sys.stdout, stderr=sys.stderr,
                            shell=True, bufsize=10000)
    
    commande = r'C:\Python27\python.exe stub.py'
    proc.communicate(commande + '\n')
    le fichier stup.py que j'utilise sert juste à m'afficher des lignes avec un petit délai entre chaque affichage, pour être plus proche de ton besoin:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    import time
     
    for percent in xrange(101):
        print("avancement: {}%".format(percent))
        time.sleep(0.1)
    au final, mon test m'affiche bien les lignes en temps réel plutôt que d'attendre la fin de la commande.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    "python -u" écrira dans le pipe en unbuffered.

    - edit -
    Cependant, si la question est:
    Citation Envoyé par tyrtamos Voir le message
    J'aimerais automatiser avec un programme Python un traitement long qui se fait d'habitude en console. Il s'agit en fait d'une conversion de format video avec l'excellent ffmpeg, dont l'exécution peut demander plus de 10 minutes.

    J'essaie alors de lancer le programme et ses arguments dans un processus (avec subprocess.Popen), mais je dois attendre que le processus soit terminé pour avoir les lignes d'affichage, alors que je voudrais l'affichage progressif pendant le traitement. comme je les ai dans la console.
    ben, on ne sait pas passer ffmpeg en mode unbuffered (comme on peut le faire pour Python ou d'autres commandes).
    Sur unix on pourrait utiliser pexpect.spawn. Ca remplace le PIPE par un pseudo terminal (pty) mais sur Windows cette feature n'existant pas en standard...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Merci pour les réponses! J'ai finalement réussi avec stdout=sys.stdout (merci Tryph!), ce qui donne un code particulièrement simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    with subprocess.Popen(commande,
                          stdout=sys.stdout,
                          stderr=sys.stdout) as proc:
        pass
    Et c'est tout!

    La commande est ici la chaine de caractères qui lancerait le programme souhaité avec ses options. Comme il s'agit d'un exécutable, on laisse l'option par défaut shell=False (shell=True n'est nécessaire que quand on veut lancer une commande shell comme "dir *.*").

    Quand on lance le programme, il vient la fenêtre de la console à l'écran, et toutes les lignes s'affichent au fur et à mesure du traitement comme souhaité. En plus, les messages d'alertes et d'erreurs s'affichent avec leur couleur comme si on avait lancé directement en console. En fait, c'est identique au lancement en console, à part qu'on peut enchainer les traitements grâce au pilotage par le code Python.

    Comme mon problème était de lancer la conversion de plusieurs fichiers vidéo ".avi" en "mp4", voilà comment je fais:

    - je trouve la liste des fichiers vidéos ".avi" à convertir dans un répertoire avec glob.glob.

    - pour chaque nom de fichier avi trouvé (=> srce), je fabrique le même nom de fichier avec l'extension .mp4 (=> dest).

    voilà le code pour la suite à placer dans la boucle des fichiers à convertir (le logiciel ffmpeg est trouvé ici: https://www.ffmpeg.org/):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    listecde = ['ffmpeg.exe', # suppose que c'est dans le PATH. Sinon: ajouter l'adresse absolue
                        '-nostdin',  # option pour empêcher les questions pendant le traitement
                        '-y', # option pour permettre de remplacer un fichier existant sans demander
                        '-i',  # précède l'adresse du fichier à convertir
                        '"' + srce + '"', # fichier à convertir (les guillemets permettent les espaces)
                        '"' + dest + '"' # nouveau fichier à écrire (les guillemets permettent les espaces)
                        ]
    commande = " ".join(listecde)
     
    with subprocess.Popen(commande,
                          stdout=sys.stdout,
                          stderr=sys.stdout) as proc:
        print("Conversion du fichier: %s\n" % (os.path.split(srce)[1],))
    Avec ça, on lance le programme le soir, et le matin, tout est fini! Pendant la journée, on peut vérifier à tous moments que le traitement continue grâce aux lignes qui s'affichent, on peut voir les messages d'erreurs éventuels, etc...

    J'aurais bien aimé avoir un plus grand contrôle sur l'affichage pour afficher les lignes dans une fenêtre PyQt mais je n'ai pas réussi. Dans un autre programme, j'avais déjà utilisé StringIO comme "file-like" pour détourner le sys.stdout", mais là ça ne marche pas, parce que subprocess utilise pour afficher la méthode fileno() qui n'existe pas avec StringIO.

    Je n'ai pas trouvé une autre solution que "stdout=sys.stdout" qui marche. Dès que l'on utilise les PIPE, on a seulement la totalité des lignes à la fin du traitement. Même d'ailleurs si on lance le code Python avec "python -u".

    Problème résolu!
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Je n'ai pas trouvé une autre solution que "stdout=sys.stdout" qui marche. Dès que l'on utilise les PIPE, on a seulement la totalité des lignes à la fin du traitement. Même d'ailleurs si on lance le code Python avec "python -u".
    Il faut quand même préciser que tous ces tracas sont dus aux PIPE de Windows.
    Sinon "python -u" fonctionne même sous Windows mais ce n'est pas un script Python qui est lancé mais ffmpeg (qui n'a pas d'équivalent pour "-u").

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour wiztricks et merci,

    Concernant le détournement de sys.stdout, connais-tu une astuce qui permettrait d'éviter l'erreur concernant fileno() générée par subprocess? J'ai essayé plusieurs solutions avec des classes mais je n'ai rien trouvé qui fonctionne. Bien sûr, ça marche avec un "vrai" fichier disque, mais pas pour l'affichage.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Concernant le détournement de sys.stdout, connais-tu une astuce qui permettrait d'éviter l'erreur concernant fileno() générée par subprocess? J'ai essayé plusieurs solutions avec des classes mais je n'ai rien trouvé qui fonctionne. Bien sûr, ça marche avec un "vrai" fichier disque, mais pas pour l'affichage.
    Le programme qu'on lance avec subprocess à besoin d'avoir des périphériques "objets systèmes externes" à qui parler indépendamment des abstractions créées par Python (car il doit pouvoir ignorer qu'il a été lancé via Python). Un StringIO est une abstraction Python qui ne correspond à aucun objet système externe, c'est juste une suite de cases mémoires du programme qui ressembleront à un fichier. C'est pour çà qu'il n'ont pas de .fileno.

    Votre problème est bien plus em... que çà car sous Windows on ne peut pas contrôler "finement" l’exécution d'un programme par un autre programme sans fabriquer des pseudo-terminaux (i.e. faire croire au programme qu'il travaille sur un terminal analogue à celui offert par la console cmd.exe). Dans ce cas, les sorties standards ne sont pas "bufferisées" (au delà de la ligne). De tels engins existent mais il faut les récupérer avec Cygwin et éventuellement installer la version de pexpect pour Windows.

    Sous Unix/Linux, on a moins de problèmes. Si vous regardez la documentation de bufsize pour Popen, on a les options 0 ou 1 pour dire nonbuffered ou linebuffered et contrôler le setup du PIPE... (mais çà ne fonctionne pas partout).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    C'est donc deux programmes différents exécutés en parallèle ?

    Tu peux les mettre en attente, en faisant attention de ne pas donner de nom de variable au résultat de Popen

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    progs = [Popen(cmd1), Popen(cmd2)]
    for prog in progs:
        prog.wait()
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  10. #10
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Merci wiztricks pour ces explications. Je comprends mieux les difficultés que j'ai rencontrées avec Windows. J'avais effectivement essayé plusieurs valeurs de bufsize (0, 1, 10000) sans aucun effet...

    Bon. Pour l'instant, j'ai ce que je voulais, et ça marche super bien! Ça prend environ 10 mn pour une vidéo de 600Mo, et ça me met par défaut les codecs video H264 et audio AAC: super! C'est parfaitement accepté, par exemple, par la nouvelle passerelle multimédia "Apple tv" (chouette machine) équipée d'un navigateur pour réseau local.

    Pour aller plus loin, j'essaierai un de ces jours avec Linux puisque mes vidéos se trouvent sur un NAS. Mais mes Linux se trouvent actuellement en machines virtuelles (virtualbox): j'attendrai de me refabriquer un PC dédié Linux pour ça.

    Merci!
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  11. #11
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    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 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Suite inattendue de mon projet.

    J'en étais resté au fait qu'avec Windows, je pouvais lancer le programme de conversion vidéo ffmpeg dans un processus (avec subprocess), mais que je devais laisser les sorties de ce programme dans la console pour les avoir en temps réel (c'est à dire pendant le traitement et pas seulement à la fin). C'était dommage, parce que ça m'empêchait de rediriger les sorties sur un widget graphique comme QTextEdit de PyQt.

    Mais comme je suis curieux (et obstiné ), j'ai essayé avec PyQt, en remplaçant subprocess par QProcess, et... ça marche!!! Non seulement le lancement du programme ffmpeg dans un processus est facile, mais les sorties sont entièrement disponibles pour en faire ce qu'on veut, y compris, bien sûr, de les afficher dans un QTextEdit en temps réel!

    Voilà le principe:

    On se trouve dans une classe héritant de QWidget par exemple (=fenêtre graphique), et on veut convertir la video source .avi en video destination .mp4.

    Voilà le lancement du processus:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    srce = "mavideo.avi"
    dest = "mavideo.mp4"
    commande = 'ffmpeg.exe -nostdin -y -i "{}" "{}"'.format(srce, dest)
     
    self.process = QtCore.QProcess(self)
     
    self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
    self.process.readyReadStandardOutput.connect(self.readStdOut)
    self.process.finished.connect(self.finprocess)
     
    self.process.start(commande, QtCore.QIODevice.ReadWrite)
    self.process.waitForStarted()
    On voit que le signal "readyReadStandardOutput", qui dit que des données sont disponibles, lancera la méthode (à créer) "readStdOut". C'est cette méthode qui permettra de récupérer les données de sortie du processus avec (le 'cp850' est l'encodage de la console cdm.exe sous Windows):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ch = str(self.process.readAllStandardOutput().data(), 'cp850').rstrip()
    On voit aussi que le signal "finished", qui dit que le processus est terminé, lancera la méthode (à créer) "finprocess" qui permettra de débrancher les liens (disconnect) et d'afficher un message pour l'utilisateur.

    Si on veut faire la conversion d'une liste de fichiers, c'est dans cette méthode "finprocess" qu'il faudra relancer un nouveau processus à la suite du précédent pour traiter le fichier suivant, etc... jusqu'à ce qu'il n'y en ait plus.

    C'est aussi simple que ça!

    Les seules choses que j'ai perdues par rapport à la console cmd.exe, ce sont les couleurs particulières d'affichage des warnings et errors (je cherche encore, mais ce n'est pas un gros problème).

    Je peux donc maintenant travailler sur un programme graphique qui me permettra de convertir mais aussi de tester et de réparer mes fichiers vidéos, ceci avec toutes les infos disponibles au fur et à mesure des traitements.

    Ouf...
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par tyrtamos Voir le message
    Mais comme je suis curieux (et obstiné ), j'ai essayé avec PyQt, en remplaçant subprocess par QProcess, et... ça marche!!! Non seulement le lancement du programme ffmpeg dans un processus est facile, mais les sorties sont entièrement disponibles pour en faire ce qu'on veut, y compris, bien sûr, de les afficher dans un QTextEdit en temps réel!
    J'avais testé, il y a longtemps, et j'ai le souvenir d'un buffering analogue. Ceci dit, dans les sources de qprocess_win de la 5.5.1, on y lit:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
    {
        // Anomymous pipes do not support asynchronous I/O. Thus we
        // create named pipes for redirecting stdout, stderr and stdin.
     
        // The write handle must be non-inheritable for input pipes.
        // The read handle must be non-inheritable for output pipes.
    En tous cas, bravo pour votre persévérance.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 11/06/2009, 09h57
  2. Réponses: 11
    Dernier message: 11/05/2009, 20h29
  3. affichage ligne par ligne du fichier ascII
    Par khayate dans le forum VB.NET
    Réponses: 15
    Dernier message: 06/06/2007, 14h14
  4. [ Problème d'affichage de données ligne par ligne ]
    Par Arkoze dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 05/06/2007, 09h45
  5. Probleme affichage avec un GtkTextView (affichage ligne par ligne)
    Par Marmoccelle dans le forum GTK+ avec C & C++
    Réponses: 9
    Dernier message: 22/03/2007, 14h42

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