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 :

Copytree, récupérer code erreur


Sujet :

Python

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 32
    Par défaut Copytree, récupérer code erreur
    bonjour à tous.
    Voici ma question, en espérant que vous saurez la résoudre

    J'ai fait un simple fichier .py pour effectuer des backups de dossier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    source = 'D:\python\dossier'
    destination = "D:\python\dossier\test"
    copyfile = copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
    assez simple ^^
    Mais voila j'aimerais un peu complexifier l'affaire.
    Quand la copie a été effectuée sans erreur j'aimerais qu'il envoi un mail par le biais d'un serveur smtp local.

    encore faisable ça (si vous avez un bon code pour smtp ça m'intéresse car sur internet on trouve mille code différent).

    Voila ou ça se complique.
    En cas d'erreur (exemple le dossier existe déjà, un fichier n'est pas lisible, ou autre) tout le script s'arrete et il déclare une erreur.

    J'aimerais que cette erreur soit reportée dans un mail qu'il enverrais pour me prévenir que la copie sait mal passée.

    Je résume

    - Copie d'un dossier
    - si ok > envoyer un simple mail (pour dire copie réussie)
    - si erreur > envoyer un mail avec si possible l'erreur (ou au moins un mail pour me dire que ça n'a pas été)

    Ca parait simple mais dès que une erreur à la copie se produit tout le script s'arrête et je ne connais pas assez copytree pour palier à ce problème.
    Je sais juste que quand la copie se passe bien il sort comme notation None
    De la je peu faire un if copytree == none (envoyer le mail)
    mais je sais pas aller plus loin dès qu'il y a une erreur.

    D'avance merci pour votre aide

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Le script s'arrête car une exception est levée. Il faut l'intercepter avec un try/except.
    Un exemple (Python 3):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    import sys, traceback
    ...
    try:
        copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
    except Exception:
        message_text = ''.join(traceback.format_exception(*sys.exc_info()))
    else: # no exception occurred
        message_text = 'copytree successful\nsource: {0}\ndestination: {1}\n'.format(source,destination)
     
    print(message_text)

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 32
    Par défaut
    nickel,
    Presque tout fonctionne parfaitement.

    Il reste un petit problème.
    Je sors l'erreur si il y en a une dans un fichier texte (info.txt)
    Vu que je travaille sous windows FR l'erreur de copie se note en francais avec des accès en genre :
    info.txt
    -------
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Traceback (most recent call last):
      File "copie.py", line 47, in <module>
     WindowsError: [Error 183] Impossible de créer un fichier déjà existant: 'test'
    Donc aucun problème.
    Je veux envoyer le fichier txt par mail (enfin lire le contenu et le renvoyer en texte par mail)
    Mais la le problème apparait (un problème avec les accents etc ...)

    Comment soit dire qu'il ne doit pas prendre en compte les accents ou alors peut être mieux.
    Faire un code pour re travailler le fichier info.txt en supprimant tout les accents.
    Genre cherche remplace tout les é,è etc ... par du code unicode.

    D'avance merci beaucoup pour votre aide
    Je suis déjà bien avancé.

  4. #4
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Il doit s'agir d'un erreur d'encodage. A quel moment l'erreur apparait ? A la lecture du fichier ou à l'envoi du mail ?

    Regarde du côté des méthodes encode et decode des strings, ou, pour l'email, du côté de email.charset et email.encoders.

    Note qu'il n'est peut-être pas nécessaire de stocker le message dans un fichier; tu pourrais garder le(s) string(s) en mémoire et les inclure dans le mail sans passer par un fichier.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 32
    Par défaut
    Je travaille avec la mémoire pour le mail.
    Je sors juste dans un fichier texte pour faire office de log.

    Dans le fichier texte il n'y a aucun problème il encode bien en utf-8 car les accents sont enregistré.
    A mon avis c'est du coté du mail qu'il a plutôt du mal.

    J'enregistre l'erreur de copytree dans cette variable : message_text

    Voici les erreurs qu'il m'affiche.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Traceback (most recent call last):
      File "copie.py", line 132, in <module>
        server.sendmail(FROM, TO, message2)
      File "D:\Softs\Python\Lib\smtplib.py", line 718, in sendmail
        (code,resp) = self.data(msg)
      File "D:\Softs\Python\Lib\smtplib.py", line 484, in data
        self.send(q)
      File "D:\Softs\Python\Lib\smtplib.py", line 305, in send
        s = s.encode("ascii")
    UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' in position 492: ordinal not in range(128)
    Merci beaucoup pour votre aide.

  6. #6
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Je m'y connais pas assez pour te dire quelle est la façon propre d'envoyer un email qui n'est pas en ASCII 7 bit (il faut jouer avec les type MIME sans doute ?).

    Peut-être quelqu'un d'autre va te répondre. En attendant, tu peux essayer d'encoder ton message avant d'appeler sendmail:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    server.sendmail(FROM, TO, message2.encode('ascii', 'xmlcharrefreplace'))
    Tu peux aussi essayer 'ignore', 'replace' et 'backslashreplace' au lieu de 'xmlcharrefreplace'.

    On dirait que sendmail attend un string unicode; il faudra peut-être jouer avec encode/decode pour arriver à quelque chose. C'est pas très propre la gestion de l'unicode en Python 2.x...

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 32
    Par défaut
    je travaille avec la version 3 de python
    ça ne fonctionne pas.
    voici le rapport d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Traceback (most recent call last):
      File "copie.py", line 125, in <module>
        server.sendmail(FROM, TO, message2.encode('ascii', 'xmlcharrefreplace'))
      File "D:\Softs\Python\Lib\smtplib.py", line 718, in sendmail
        (code,resp) = self.data(msg)
      File "D:\Softs\Python\Lib\smtplib.py", line 480, in data
        q = quotedata(msg)
      File "D:\Softs\Python\Lib\smtplib.py", line 157, in quotedata
        re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
      File "D:\Softs\Python\Lib\re.py", line 166, in sub
        return _compile(pattern, flags).sub(repl, string, count)
    TypeError: can't use a string pattern on a bytes-like object
    J'avoue que sur ce coup la je suis largué.
    J'ai essayé plein de truc mais ça ne marche pas.
    Bon ici j'ai bricolé un truc ou il cherche et remplace les é è à etc ... mais c'est vraiment du bricolage ^^

  8. #8
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    En Python 3, c'est plus facile d'expliquer ce qui se passe:

    message2 est un string (unicode)
    message2.encode('ascii', 'xmlcharrefreplace') est une liste de bytes

    La fonction sendmail attend un string (unicode) pas une liste de bytes, d'où l'erreur.

    message2.encode('ascii', 'xmlcharrefreplace').decode('ascii') va retransformer la liste de bytes en un string, en ayant remplacé tout caractère non-ascii par une référence de caractère XML; ça devrait passer.

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Si dividee dit que ça va marcher, je n’ai rien à dire de plus sur ce plan.





    Mais une petite remarque:

    je vois qu’il y a dans ton code une expression
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
    La fin \r(?!\n) est inutile sous cette forme.

    En effet quand le moteur de regex en arive à devoir tester si \r(?!\n) matche, c’est que les deux précédentes options \r\n et \n ont échoué => ce n’est pas la peine de lui faire tester s’il y a '\r' non suivi de '\n' , le moteur de regex a déjà testé que cette possibilité de voir un '\r' suivi de '\n' n’existait pas. Donc s'il y a matching de \r avec un '\r' , c'est assurément un '\r' sans '\n' après.

    Donc on peut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    re.sub(r'(?:\r\n|\n|\r)', CRLF, data))








    D’autre part, il n’y a pas besoin de mettre r devant la chaîne qui constitue la RE passée comme argument au compilateur de regex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    re.sub('(?:\r\n|\n|\r(?!\n))', CRLF, data))
    # suffit à la place de
    re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))


    En effet, ton but est d’indiquer des caractères CR et LF au compilateur de regex.

    Or pour le compilateur,

    recevoir un objet de type string assurant la représentation binaire d’une chaîne ’ bla\n’ comportant (c’est l’objet string qui comporte) la succession de caractères b l a LF

    ou recevoir un objet de type string assurant la représentation binaire d’une chaîne ’ bla\\n’ comportant (c’est l’objet qui comporte) la succession de caractères b l a antislash n

    c’est pareil:

    dans les deux cas il va créer un objet Regex qui comportera une succession de symboles (objets) b l a LF


    Il empoigne en effet la succession de deux caractères objets antislash LF contenue dans l’objet string qu’il reçoit (car il reçoit bien un objet, pas une chaîne telle qu’on la voit en affichage écrite sur écran) de la même façon que le fait le lecteur de chaîne qui crée un objet de type string à partir de l’écriture ’\n’ :

    il considère l’antislash comme un métacaractère et il crée une représentation interne (en bits) qui signifie LF à partir des deux indications antislash LF contenues dans l’objet string.

    Or, écrire r’\n’ étant identique (au niveau primaire des chaînes et des objets string) à écrire ’\\n’ , on voit qu’écrire r’\n’ dans une RE passée en argument à un compilateur de regex n’a aucun intérêt.



    C’est un peu compliqué mais ce n’est pas ma faute.

    Ou alors je n’ai vraiment encore rien compris et je raconte n’importe quoi, ce qui n’est pas à exclure....

    Mais enfin, tout ce baratin explique quand même l’illustration suivante:

    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 re
     
    def what_match(RE,ch):
        print repr(RE)
        if re.search(RE,ch):
            print 'match =',re.search(RE,ch).group()
        else:
            print 'PAS DE MATCH'
        print
     
    ch = 'jacinthe\\tamaranthe\tjasmin'
    print 'len(ch) =',len(ch)
    print 'repr(ch) =',repr(ch)
    print 'ch =',ch,'\n'
    what_match('.{5}the\t',ch)   #1
    what_match('.{5}the\\t',ch)  #2
    what_match(r'.{5}the\t',ch)  #3
    what_match(r'.{5}the\\t',ch) #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
    len(ch) = 26
    repr(ch) = 'jacinthe\\tamaranthe\tjasmin'
    ch = jacinthe\tamaranthe	jasmin 
     
    '.{5}the\t'
    match = maranthe	ZZZZ
     
    '.{5}the\\t'
    match = maranthe	ZZZZ
     
    '.{5}the\\t'
    match = maranthe	ZZZZ
     
    '.{5}the\\\\t'
    match = jacinthe\tZZZZ

    ch = 'jacinthe\\tamaranthe\tjasmin'
    –> l’objet de bits représentant ch est la succession d’objets
    j a c i n t h e antislash t a m a r a n t h e TABULATION j a s m i n



    Dans le cas #1, la RE '.{5}the\t' donne un objet de type string dont le dernier caractère est une TABULATION, d’où un objet Regex (ce que j’appelle une regex) dont le dernier symbole est un symbole TABULATION . C’est fantastique cette logique, n’est ce pas ?

    Donc la regex réagit sur marantheTABULATION
    c'est à dire 'maranthe\t'



    Dans le cas #2, la RE '.{5}the\\t' donne un objet string qui se termine par antislash TABULATION ==> d’où une regex symbolisant TABULATION à la fin (et non pas antislash TABULATION, en vertu de ce que j’ai expliqué plus haut).

    Donc ça réagit sur marantheTABULATION aussi
    c'est à dire 'maranthe\t'



    Dans le cas #3, la RE r'.{5}the\t' est identique à '.{5}the\\t' donc même résultat que précédent, encore.



    Enfin dans le cas #4, la RE r'.{5}the\\t' est identique à '.{5}the\\\\t' et donne un objet string qui se termine par antislash antislash t

    Alors de ce fait quand le compilateur de regex reçoit l’objet string qui constitue la représentation machine de la RE, il interprète cette succession antislash antislah t de la façon suivante:

    le premier antislah est pris comme un métacaractère, ce qui se traduit par le fait que le second antislash est saisi comme signifiant un antislash et non pas comme métacaractère modulant le caractère suivant; et par conséquent le t suivant reste considéré comme un t.

    Donc pour résumer, la regex se termine par t h e antislash t ( un seul antislash).

    De ce fait la regex réagit non plus sur marantheTABULATION mais sur j a c i n t h e antislash t
    c'est à dire 'jacinthe\\t'

    Ça colle. Ouf

  10. #10
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    eyquem, tu es en train de corriger le module smtplib de la librairie standard, pas son code à lui

Discussions similaires

  1. makefile récupérer code erreur
    Par boris_couturier dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 24/05/2011, 17h47
  2. Récupérer code erreur avec Firebird et Zeoslib
    Par seabs dans le forum Bases de données
    Réponses: 4
    Dernier message: 28/06/2010, 16h28
  3. Récupérer code erreur dans une log
    Par clluciole dans le forum Développement
    Réponses: 1
    Dernier message: 03/08/2009, 15h20
  4. Récupérer le code erreur du convert
    Par ALEX731 dans le forum Sybase
    Réponses: 7
    Dernier message: 03/04/2007, 10h05
  5. [Mail] récupérer les code erreurs de mail()
    Par Djakisback dans le forum Langage
    Réponses: 2
    Dernier message: 22/03/2006, 17h19

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