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

Réseau/Web Python Discussion :

FTP.storlines semble bloquant


Sujet :

Réseau/Web Python

  1. #1
    Membre averti Avatar de Stopher
    Homme Profil pro
    Responsable technique
    Inscrit en
    Juin 2004
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Responsable technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 198
    Points : 446
    Points
    446
    Par défaut FTP.storlines semble bloquant
    Bonjour ,

    j'ai un problème concernant FTP.storlines , en effet , j'ai développé un petit bout de code qui rapatrie ( via FTP ) des fichiers déposés par des clients ( de 0 à 300Mo )

    Une fois le transfert terminé , une notification est envoyé par mail pour avertir de l'arrivé des nouveaux fichiers .

    les états sont gérés par mysql ( MySQLdb )

    Tout fonctionne correctement sauf lorsque le fichier est d'une taille > 200Mo .

    Dans ce cas , le fichier est transféré en totalité mais mon script de me donne aucune notification , comme si FTP.storlines gardai la main sans jamais la rendre .

    Voici un bout de mon code .. qui selon moi pose probléme .

    Merci d'avance pour votre aide

    Ch.

    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
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
     
    ...
    #action du thread ( start )
        def run(self):
     
            #Signale que l'on met en file le fichier
            self.logger.info("%s -- INFO -- Attente du thread -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
            #aquisition d'un jeton ( semaphore ) ou attente d'une libération
            self.sem.acquire()
     
            #Changement d'état en base => 2 upload en cours
            self.sql.execute("UPDATE "+str(self.conf.get("DDB","TBL_ETAT"))+" SET "+str(self.conf.get("DDB","CHAMP_ETAT"))+" = 2 WHERE "+str(self.conf.get("DDB","CHAMP_ID"))+" = "+str(self.file[0]))
     
            try:
                #jeton acquis , signalement du lancement de l'upload du fichier
                self.logger.info("%s -- INFO -- Execution du thread -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
                #envoie du fichier au module FTP
                cret = self._send_file()
     
                #test du code retour 0 = OK
                if(cret != 1):
     
                    #Changement d'état en base => 3 upload terminé si tout est ok
                    self.sql.execute("UPDATE "+str(self.conf.get("DDB","TBL_ETAT"))+" SET "+str(self.conf.get("DDB","CHAMP_ETAT"))+" = 3 WHERE "+str(self.conf.get("DDB","CHAMP_ID"))+" = "+str(self.file[0]))
     
                    #notification 
                    self.notify_by_mail('data_newfilenotify')
                    self.logger.info("%s -- INFO -- Notify new file -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
                else:
                    #remet l'etat du fichier à 0 pour reesayer
                    self.sql.execute("UPDATE "+str(self.conf.get("DDB","TBL_ETAT"))+" SET "+str(self.conf.get("DDB","CHAMP_ETAT"))+" = 0 WHERE "+str(self.conf.get("DDB","CHAMP_ID"))+" = "+str(self.file[0]))
     
                    #notification 
                    self.notify_by_mail('data_retryfilenotify')
                    self.logger.info("%s -- ERR -- Notify retry file -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
            finally:
                #signalement de la fin de l'upload donc du thread
                self.logger.info("%s -- INFO -- Fin du thread -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
                #libération du jeton pour laisser la place à un autre
                self.sem.release()
     
     
     
        #Méthode _send_file gére les transactions avec le serveur FTP 
        def _send_file(self):
     
            try:
                #ouverture du fichier data
                f = open(self.file[3]+self.file[1],'rb')
     
            except IOError:
                #erreur à l'ouverture du fichier
                self.logger.info('%s -- ERR -- sendFile error opening [%s] -- etat devient 404' % (strftime('%c',gmtime()), self.file[1]) )
     
                #Changement d'état en base => 404 Fichier introuvable
                self.sql.execute("UPDATE "+str(self.conf.get("DDB","TBL_ETAT"))+" SET "+str(self.conf.get("DDB","CHAMP_ETAT"))+" = 404 WHERE "+str(self.conf.get("DDB","CHAMP_ID"))+" = "+str(self.file[0]))
     
                #notification erreur
                self.notify_by_mail('data_emergencynotify')
                self.logger.info("%s -- INFO -- Notify error -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
                #quit la fonction
                return 1
     
     
            try:
                #connection au serveur FTP
                ftp =   FTP( self.conf.get("FTP", "HOST") )
                #Login avec user <-> password
                ftp.login( self.conf.get("FTP", "USER"), self.conf.get("FTP", "PASSWORD"))
     
                try:
                    #creation du repertoire destination
                    self.logger.info("%s -- INFO -- Creation repertoire -- %s"% (strftime('%c',gmtime()), self.file[4]) )
                    ftp.mkd(self.file[4])
     
                except error_perm, resp:
     
                    #si le repertoire existe déjà .. on signale et on passe
                    self.logger.info("%s -- WARN -- Repertoire deja existant -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
                finally:
     
                    #on se déplace dans le repertoire finale
                    ftp.cwd(self.file[4])
     
                    #info du lancement d'upload du fichier
                    self.logger.info("%s -- INFO -- Depot du fichier -- %s"% (strftime('%c',gmtime()), self.file[1]) )
     
                    try:
     
                        #Lancement de l'upload proprement dit#
                        ftp.storbinary('STOR %s' %self.file[1], f)
     
                    except all_errors, resp:
     
                        #remet l'etat du fichier à 0 pour reesayer
                        self.sql.execute("UPDATE "+str(self.conf.get("DDB","TBL_ETAT"))+" SET "+str(self.conf.get("DDB","CHAMP_ETAT"))+" = 0 WHERE "+str(self.conf.get("DDB","CHAMP_ID"))+" = "+str(self.file[0]))
     
                        self.logger.info("%s -- ERR -- %s etat devient 0 Erreur transfert du fichier -- %s"% (strftime('%c',gmtime()), resp, self.file[1]) )
                        #Retour erreur
                        return 1
     
                #code retour
                return 0
     
            except error_perm, resp:
     
                #Changement d'état en base => 500 Probleme de connection ou d'ecriture
                self.sql.execute("UPDATE "+str(self.conf.get("DDB","TBL_ETAT"))+" SET "+str(self.conf.get("DDB","CHAMP_ETAT"))+" = 500 WHERE "+str(self.conf.get("DDB","CHAMP_ID"))+" = "+str(self.file[0]))
     
                self.logger.info("%s -- ERR -- %s etat devient 500 -- %s"% (strftime('%c',gmtime()), resp, self.file[1]) )
     
                #notification erreur
                self.logger.info("%s -- INFO -- Notify error -- %s"% (strftime('%c',gmtime()), self.file[1]) )
                self.notify_by_mail('data_emergencynotify')
     
                return 1
     
            except all_errors, resp:
     
                #Changement d'état en base => 500 Probleme de connection ou d'ecriture
                self.sql.execute("UPDATE "+str(self.conf.get("DDB","TBL_ETAT"))+" SET "+str(self.conf.get("DDB","CHAMP_ETAT"))+" = 500 WHERE "+str(self.conf.get("DDB","CHAMP_ID"))+" = "+str(self.file[0]))
     
                self.logger.info("%s -- ERR -- %s etat devient 500 -- %s"% (strftime('%c',gmtime()), resp, self.file[1]) )
     
                #notification erreur
                self.logger.info("%s -- INFO -- Notify error -- %s"% (strftime('%c',gmtime()), self.file[1]) )
                self.notify_by_mail('data_emergencynotify')
     
                return 1
     
            finally:
     
                #fermeture du fichier
                self.logger.info("%s -- INFO -- Fermeture du fichier -- %s"% (strftime('%c',gmtime()), self.file[1]) )
                f.close()
                #cloture de la connection FTP
                self.logger.info("%s -- INFO -- Deconnection du FTP -- %s"% (strftime('%c',gmtime()), self.file[1]) )
                ftp.quit()
    ...

  2. #2
    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,
    Si vous suivez la piste "çà bloque lors de transferts de gros fichiers", c'est une histoire entre ftplib et le serveur FTP 'en face'.

    Personnellement, j'essaierai de reproduire le problème après avoir enlevé tout ce qui est 'non fonctionnel': threads, mail, database,...
    Si le problème se reproduit avec ce script réduit, vous pourrez regarder côté serveur FTP - il a des logs? est ce qu'il supporte le transfert via un client ftp ou curl?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre averti Avatar de Stopher
    Homme Profil pro
    Responsable technique
    Inscrit en
    Juin 2004
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Responsable technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 198
    Points : 446
    Points
    446
    Par défaut
    Merci pour la réponse ,

    l'aspect thread/mail/log a été vérifié , la gestion des logs m'a d'ailleurs permis de voir exactement ou se situe le probléme ( endroit exact du bloquage )

    à savoir à la ligne suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #Lancement de l'upload proprement dit#
    ftp.storbinary('STOR %s' %self.file[1], f)
    Le transfert s'effectue correctement et entièrement mais la fin du transfert justement ne semble pas être détecté ..

    J'ai testé mon script sur un autre serveur ( debian + vsftpd ) et là .. plus de problème ...

    J'ai donc cherché du coté de Serv-U , en augmentant sensiblement le timeout des trames et désactivé le timeout adaptatif ... ( bien que je ne sache pas exactement la finalité de cette option sur servU ).

    Resultat ... parfait les fichiers de taille supérieurs à 200 Mo passent maintenant sans aucun problème , la fin est détecté les états changés et les notifications envoyées ...

    Victoire ? en tout cas mon système de transfert de fichiers "régulé" est fonctionnel ...

    100 à 150 fichiers / jour pour le moment ... Je surveille la moindre erreur ... cependant , si vous avez plus d'informations sur ce qui a pu se passer .. je suis preneur .

    Pour moi, je pense que le problème de timeout aurait pu être résolu si la détection de déconnexion ( commande ), était possible pour se re-connecter et lancer une reprise d'upload pour enfin avoir un retour du serveur comme quoi le fichier est bien arrivé .

    Bonne soirée ,

    Ch.

  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,
    Pour moi, je pense que le problème de timeout aurait pu être résolu si la détection de déconnexion ( commande ), était possible pour se re-connecter et lancer une reprise d'upload pour enfin avoir un retour du serveur comme quoi le fichier est bien arrivé .
    ftp (et ftplib) permet une reprise du transfert en cas de soucis dont la probabilité ne peut qu'augmenter avec la taille des fichiers et le nombre de copies. Après c'est une question de programmation.
    - W.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre averti Avatar de Stopher
    Homme Profil pro
    Responsable technique
    Inscrit en
    Juin 2004
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Responsable technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 198
    Points : 446
    Points
    446
    Par défaut
    Ok , merci pour cette info ,


    Malgres le bon fonctionnement aujourd'hui, je vais essayer d'ajouter cette fonctionnalité et remettre les paramètres du serveur par défaut .

    Merci encore pour votre aide .

    ch

  6. #6
    Membre averti Avatar de Stopher
    Homme Profil pro
    Responsable technique
    Inscrit en
    Juin 2004
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Responsable technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 198
    Points : 446
    Points
    446
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,


    ftp (et ftplib) permet une reprise du transfert en cas de soucis dont la probabilité ne peut qu'augmenter avec la taille des fichiers et le nombre de copies. Après c'est une question de programmation.
    - W.
    Arf ...

    je tente la reprise de transfert via ftplib .. mais je parviens pas à mes fins ..

    Auriez-vous des pistes à suivre pour accomplir cette tâche ?

    Merci d'avance ,
    Christophe.

  7. #7
    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,
    Je n'ai rien qui puisse être utilisable via cut&paste.
    Juste le brico ci-dessous qui exploite les points clés: timeout, reprise,... mais dans un contexte un peu différent.
    - W
    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
    import os
    import ftplib
    import sys
     
    from functools import partial
    def get_names(source):
        target = os.path.basename(source)
        part = target + '.part'
        return target, part
     
     
     
    class MyFtp(object):
        def __init__(self, host, uname='anonymous', pwd='guest', tmo=30):
            ftp = self._ftp = ftplib.FTP(host, timeout=tmo)
            ftp.login(uname, pwd)
     
        def write_bytes(self, f, content):
            self._done += len(content)
            print '%.02f%%' % (float(self._done) / float(self._size))
            f.write(content)
     
        def get_binary(self, source):
     
            ftp = self._ftp
            self._size = ftp.size(source)
            target, part = get_names(source)
            if os.path.exists(part):
                self._done = os.path.getsize(part)
                print '** found part file, trying to restart at offset %d' % self._done
            else: self._done = 0
     
            with open(part, 'ab') as f:
                cb = partial(self.write_bytes, f)
                try:
                   ftp.retrbinary("RETR " + source, cb, rest=self._done)
     
                except Exception as e:
                    print e
                else:
                    os.rename(part, target)
     
    if __name__ == '__main__':
     
        small = "pub/lfs/conglomeration/bash/bash-3.2-fixes-8.patch"
        large = "pub/lfs/hlfs-packages/hlfs-packages-unstable-20080712.tar"
        medium = 'pub/lfs/conglomeration/bash/bash-doc-3.2.tar.gz'
        source = small
     
        ftp = MyFtp("ftp.aliensoft.org")
        ftp.get_binary(source)
     
        target, part = get_names(source)
        if os.path.exists(part):
            print 'transfer has failed, retrieved only %d bytes' % os.path.getsize(part)
        elif os.path.exists(target):
            print 'created %s, size=%d bytes' % (target, os.path.getsize(target))
        else: print 'neither found part or full file'
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. [] [Réseau] Renommer des fichiers dans un site FTP
    Par JerBi dans le forum VB 6 et antérieur
    Réponses: 10
    Dernier message: 22/08/2003, 00h35
  2. [] [Réseau] Liste des répertoires d'un FTP
    Par Maitre Kanter dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 12/03/2003, 16h39
  3. [] [Réseau] Transfert fichier sur un FTP
    Par CYFL dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 26/02/2003, 17h33
  4. FTP et D5
    Par sdidier dans le forum Web & réseau
    Réponses: 2
    Dernier message: 17/07/2002, 10h45
  5. Problème de transfert FTP sous IIS
    Par thanathz dans le forum Développement
    Réponses: 2
    Dernier message: 12/07/2002, 15h27

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