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 :

création d'une upload queue ftplib


Sujet :

Python

  1. #1
    Futur Membre du Club
    Homme Profil pro
    infographiste3d
    Inscrit en
    Octobre 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : infographiste3d
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Octobre 2011
    Messages : 19
    Points : 6
    Points
    6
    Par défaut création d'une upload queue ftplib
    Bonjour,

    J ai fais un petit programme qui permet de placer des fichiers sur un serveur ftp, en visualisant la progression dans l interface.

    Chaque upload de fichier est fait dans un thread diffférent. Ce qui permet de ne pas bloquer mon interface et de continuer à ajouter de nouveaux fichiers.
    le thread met egalement à jour la barre de progression de l'upload.

    Mon souci c'est qu'à chaque ajout de fichier un nouveau thread part et que ma bande passante est divisée entre ces différents fichiers en upload.

    Je cherche un moyen de bloquer les threads le temps que les uploads precedent ne sont pas fini.

    Je vous ai refais un petit exemple fonctionnel pour illustrer mon problème.

    merci

    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
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    #####################################################
    #fonction extern
    import os, sys, re, subprocess
    import Tix ,time
    import tkFileDialog
    import threading
    import ftplib
     
     
    class uploadLauncher_MainClass(Tix.Tk):
        def __init__(self,parent):
            Tix.Tk.__init__(self,parent)
            self.parent = parent
            self.initialize()
            self.threadcount=0
     
        def initialize(self):    
            self.grid()
            ###########FtpUpload########################
            Sendbutton = Tix.Button(self,text=u"FtpUpload",command=self.FtpUp)
            Sendbutton.grid(column=3,row=2,columnspan=1)
            self.grid_columnconfigure(1,weight=3)
            self.grid_columnconfigure(4,weight=1)
            self.grid_columnconfigure(5,weight=3)
            self.resizable(True,False)
     
        def FtpUp(self):
                """fonction appelle par le bouton qui lance un thread par fichier a uploader"""
                self.sendLst="fichier1","fichier2","fichier3","fichier4"
                self.threadFtp={}
                self.meter={}
                self.cancelbtn={}
                for file in self.sendLst:
                        localfile='d:\\'+file+'.mpg' 
                        distantfile='/data/'+file+'.mpg'
     
                        ### recup de la taille du fichier
                        taille= os.path.getsize(localfile)
     
                        self.threadcount=self.threadcount+1
                        self.threadFtp[self.threadcount]=ftpUpThread(self,self.threadcount,localfile,distantfile,taille)
     
                        #creation de la bar de progression 
                        self.meter[self.threadcount] = Tix.Meter(self, text=os.path.split(localfile)[1], value=0.)
                        self.meter[self.threadcount].grid(row = self.threadcount+2, column =1 ,columnspan=2, padx = 3, pady = 3,sticky ='EW')
     
                        #creation du bouton d interuption de l upload
                        self.cancelbtn[self.threadcount] = Tix.Button(self,text=u"cancel",command=self.threadFtp[self.threadcount].cancel)
                        self.cancelbtn[self.threadcount].grid(row=self.threadcount+2,column=3,columnspan=1)
                        self.threadFtp[self.threadcount].start() 
     
     
     
        def forget(self,threadcount):
                     self.cancelbtn[threadcount].destroy()
                     self.meter[threadcount].destroy() 
     
    class ftpUpThread(threading.Thread):
        def __init__(self,parent,threadcount,localfile,distantfile,taille):
            self.threadcount=threadcount
            self.parent=parent
            self.distantfile= distantfile     
            self.localfile= localfile
            self.taille= taille
            self.sizeWritten=0
            threading.Thread.__init__(self)
            self._stopevent = threading.Event( ) 
     
        def callback(self,test):
            """met a jour la bare de progression et coupe la connection si on appuis sur cancel"""
            self.sizeWritten += 8192
            app.meter[self.threadcount].config(value=(float(self.sizeWritten)/float(self.taille)))
            app.meter[self.threadcount].update()
            if self._stopevent.isSet(): 
                    self.ftp.abort()
                    self.ftp.sendcmd('close')
                    print "abandon du transfert" 
     
        def cancel(self):
            """passe le stop event en true et efface les widgets correspondant au thread"""    
            self.parent.forget(self.threadcount)  
            self._stopevent.set( )
     
     
        def run(self):
            ###connexion ftp
            self.ftp = ftplib.FTP( )
            self.ftp.connect('un_serveurftp ', 21)
            self.ftp.login('log', 'pass')
            print self.ftp.getwelcome()
     
            ###creation du rep: 
            print os.path.split(self.distantfile)[0]
            try: self.ftp.mkd(os.path.split(self.distantfile)[0])
            except  Exception, err: print err
            print "command envoyer"
            ###envoie fichier
            file = open(self.localfile, 'rb') # ici, j'ouvre le fichier ftp.py 
     
            try: self.ftp.storbinary('STOR '+self.distantfile, file, 8192 ,self.callback) # ici (ou connect est encore la variable de la connexion), j indique le fichier a envoyer
            except  Exception, err: print err
            file.close() # on ferme le fichier
            self.parent.forget(self.threadcount)
            self.ftp.quit()
     
    if __name__ == "__main__":
     
        app = uploadLauncher_MainClass(None,)
        app.title('uploadLauncher')
        app.mainloop()

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

    En général, un serveur donne le nombre maxi de connexions acceptées. Dans ce cas, la solution est simple:

    => dans la partie principale du programme (thread principal), on teste dans une boucle threading.active_count() qui donne le nombre de threads actifs, et on n'en lance un autre que si ce nombre est inférieur au maxi, et s'il y a encore un fichier à uploader.

  3. #3
    Futur Membre du Club
    Homme Profil pro
    infographiste3d
    Inscrit en
    Octobre 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : infographiste3d
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Octobre 2011
    Messages : 19
    Points : 6
    Points
    6
    Par défaut
    merci,

    Je crois que je commence à comprendre, je vais tester ça.

    lucas

  4. #4
    Futur Membre du Club
    Homme Profil pro
    infographiste3d
    Inscrit en
    Octobre 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : infographiste3d
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Octobre 2011
    Messages : 19
    Points : 6
    Points
    6
    Par défaut
    Cette boucle, comment dois je l'ajouter? Je dois forcement passer par un autre thread non? il ferait le teste du nombre des threads d'upload ftp et en lancerais l'upload suivant si besoin.
    je suis dans juste?

    merci

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

    Je n'ai pas beaucoup regardé ton code, et je n'ai pas travaillé avec tkinter depuis longtemps, mais, a priori, voilà ce que je ferais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    fichiers = [fic1, fic2, ...]
    nbcnxmaxi = 10
    while fichiers!=[]:
        if  threading.active_count()<nbcnxmaxi:
            fichier = fichiers.pop(0)
            lancement du thread d'upload de fichier
        redonner la main au graphique pour éviter qu'il ne fige
        time.speed(0.1) #pour ne pas que la boucle consomme trop de ressources
    On peut placer cette boucle dans FtpUp au lieu de la boucle 'for'.

    Attention, dans les bibliothèques graphiques, il n'est pas recommandé d'avoir des instructions graphiques dans les threads (=> app.meter): ceux-ci doivent envoyer les instructions graphiques par l'intermédiaire de messages. Mais je ne sais plus comment ça marche avec tkinter.

    Ok?

  6. #6
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    En fait, perso, je ferais ça légèrement différemment, en lançant un nombre donné de threads dès le début, et en leur passant à tous la même queue. Chacun de ces threads est alors une boucle sans fin (qui sleep(0.1) quand elle n’a rien à faire) récupérant un élément dans la queue et le téléchargeant. Le code (thread) principal n’a alors plus qu’à “nourrir” la queue (qui est nativement thread-safe).

    D’ailleurs, en py3, il y a un nouveau module qui simplifie encore ce genre de truc*: concurrent.futures (y a même un exemple de téléchargement, basé sur urllib)…

  7. #7
    Futur Membre du Club
    Homme Profil pro
    infographiste3d
    Inscrit en
    Octobre 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : infographiste3d
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Octobre 2011
    Messages : 19
    Points : 6
    Points
    6
    Par défaut
    Merci, a tout le deux

    à tyrtamos:

    ok je comprend. En fait je pensais à un thread séparé parce que je ne voyais pas de solution pour redonner la main à l'interface pendant la boucle while.
    Je ne savais pas que c était possible de faire ça avec une interface.
    je vais chercher pour faire ça avec tkinter

    à mont29:

    ça à l air très bien comme solution je vais voir la faisabilité de la chose avec la version 2.7 de python

    lucas

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

    Citation Envoyé par lucaskywalker Voir le message
    redonner la main à l'interface pendant la boucle while
    Je crois me rappeler que c'est avec la méthode .update_idletasks() qu'on fait ça. Mais pour être sûr: regarde avec le forum tkinter!

  9. #9
    Futur Membre du Club
    Homme Profil pro
    infographiste3d
    Inscrit en
    Octobre 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Jura (Franche Comté)

    Informations professionnelles :
    Activité : infographiste3d
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Octobre 2011
    Messages : 19
    Points : 6
    Points
    6
    Par défaut
    merci beaucoup tyrtamos

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

Discussions similaires

  1. Création d'une queue
    Par OlivierDotre dans le forum C
    Réponses: 9
    Dernier message: 16/08/2007, 19h27
  2. Réponses: 2
    Dernier message: 26/04/2007, 14h04
  3. Création d'une base avec IbConsole
    Par Lucien dans le forum Outils
    Réponses: 3
    Dernier message: 02/03/2004, 18h34
  4. création d'une batabse .gdb
    Par jejestyle dans le forum Bases de données
    Réponses: 3
    Dernier message: 23/02/2004, 00h29
  5. [BES] Création d'une variable d'environnement
    Par NGI80 dans le forum Autres
    Réponses: 2
    Dernier message: 17/10/2002, 07h31

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