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 :

Lire un fichier texte par bloc de lignes


Sujet :

Python

  1. #1
    Membre confirmé Avatar de dodineau
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    100
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 100
    Par défaut Lire un fichier texte par bloc de lignes
    Bonjour,
    J'ai un programme qui crée un fichier texte de plein de lignes (en multiple de 5).
    Je voudrais donc pouvoir relire ce fichier 5 lignes par 5 lignes.

    Voici la partie de mon code qui ne lit pas comme je voudrais.

    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
     
    source = open('temp_lecture.txt', 'w')
     
    source.write('aa\n')
    source.write('bb\n')
    source.write('cc\n')
    source.write('dd\n')
    source.write('ee\n')
    source.write('ff\n')
    source.write('gg\n')
    source.write('hh\n')
    source.write('ii\n')
    source.write('jj\n')
    source.write('kk\n')
    source.write('ll\n')
    source.write('mm\n')
    source.write('nn\n')
    source.write('suivant\n')
    source.close()
     
    source = open('temp_lecture.txt', 'r')
    for i in source:
        l1=source.readline()
        l1=l1[:len(l1)-1]
        print(l1)
     
        l2=source.readline()
        l2=l2[:len(l2)-1]
        print(l2)
     
        l3 = source.readline()
        l3 = l3[:len(l3)-1]
        print(l3)
     
        l4=source.readline()   
        l4 = l4[:len(l4)-1]
        print(l4)
     
     
        l5=source.readline()
        print(l5)
     
        #Traitement des 5 lignes
     
    source.close()
    Déjà ce code ne lit pas la 1ere ligne et ensuite j'ai un décalage d'une ligne à chaque lecture d'un bloc de 5.

    Merci pour votre aide.
    A+

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Salut,

    Il faudrait réfléchir un peu à ce que vous faites plutôt que d'écrire n'importe quoi et venir ici râler "çà ne marche pas".

    Relisez votre code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    source = open('temp_lecture.txt', 'r')
    for i in source:
        l1=source.readline()
    soit vous lisez vos lignes via for i in source et dans le corps de la boucle la ligne est associée à la variable i. Soit vous faites une boucle while True et vous lisez une ou plusieurs lignes dans le corps de la boucle.

    A vous de choisir en fonction de ce que vous voulez faire et écrire un code qui "cohérent" par rapport à ce choix.

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

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par dodineau Voir le message
    Je voudrais donc pouvoir relire ce fichier 5 lignes par 5 lignes.
    Je ne comprends pas ce point. Admettons que tu lises 5 lignes d'un coup, que veux-tu en faire ensuite ? Les afficher ? Les stocker ? Dans ce cas, autant les afficher ou les stocker une par une...

    Mis à part ce détail, tu peux t'orienter vers la fonction source.readlines() qui te lit tout le fichier et te renvoie un tableau de lignes. Une fois le tableau récupéré, les slices te permettront de le gérer 5 éléments par 5 éléments.
    Ou alors un enumerate(source, 1) qui te donnera chaque ligne précédée d'un nombre énuméré. Chaque fois que ce nombre atteint un multiple de 5 alors tu as tes 5 lignes.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 334
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 334
    Par défaut
    bonjour,
    Un fichier est un itérateur, donc comme dit par wiztricks, pas la peine de lire en plus les lignes - Et avec les itérateurs tu as next() qui foit correspondre à ce que tu désires

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     for line in source:
        line = line.rstrip()
        for i in range(0, 4):
            line += " - " + next(source).rstrip()
        print(line) # ou yield
    ps: ajouter une gestion d'exception si le nombre de ligne n'est pas multiple de 5

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Salut,

    Pourquoi écrire 2 boucles imbriquées?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     for line in source:
        line = line.rstrip()
        for i in range(0, 4):
            line += " - " + next(source).rstrip()
        print(line) # ou yield
    le code suivant donne le même résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    lines = []
    for _ in range(5):
        lines.append(source.readline().rstrip())
    print(' - '.join(lines)
    Ici on fait le choix de fabriquer une liste de lignes (au moins) pour deux raisons:
    • pour avoir une suite de lignes plus facile à utiliser qu'une chaine de caractères à redécouper via une fin de ligne ou un séparateur de lignes,
    • parce qu'on pense qu'il est plus efficace d'ajouter un objet à une liste que de créer une nouvelle chaine de caractères par la concaténation de 2 autres (ce qui n'empêche pas de mettre toutes ces lignes dans une seule chaines de... histoire de l'afficher de façon plus lisible avec print).

    Et je préfère utiliser .readline() plutôt que "next" parce que si tant est qu'on ait à gérer un nombre de lignes restantes inférieur à 5, il sera plus simple d'ajouter une condition qu'un block try...except StopIteration.

    L'étape suivante est d'arriver à penser "fonction" i.e. donner un nom a cette opération, définir des arguments et l'objet retourné pour traduire "retourne les 5 lignes suivantes".

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

  6. #6
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 901
    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 : 4 901
    Par défaut
    Bonjour,

    Une autre manière ICI qui fonctionne très bien,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from itertools import islice
     
    def next_line(f, n=1):
        return [line.strip() for line in islice(f, n)]
     
    with open("temp_lecture.txt", "r") as f:
        lines = next_line(f, n=5)
        while lines:
            print(lines)
            lines = next_line(f, n=5)
    Bonne continuation...

  7. #7
    Membre confirmé Avatar de dodineau
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    100
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 100
    Par défaut
    Bonjour et merci pour toutes ces réponses.
    Je veux lire par bloc de 5 lignes car je suis en train de réaliser un envoi de mails suivant une liste.
    Cette liste est composée de multiples de 5 lignes : expéditeur, destinataire, sujet, message, commentaires.
    Je lis donc 5 lignes du fichier et j'envoie le mail. Si le mail ne part pas j'envoie ces 5 lignes dans un nouveau fichier temporaire. Si le mail part je n'envoie rien et je recommence à lire les 5 lignes suivantes jusqu'à la fin.
    A la fin du traitement du fichier d'origine j'écrase le fichier origine par le fichier temporaire.

    Voici mon code, il n'est pas abouti mais il fonctionne comme je le désire.
    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
     
    #!/usr/bin/env python3
     
    import subprocess, os
    import sys
     
    if os.path.exists('outbox.txt')==False:
        print("Pas de fichier à traiter")
        sys.exit()
    #if
     
    subprocess.call('sudo rm mail_temp.txt', shell=True)
     
    source = open('outbox.txt', 'r')
    lines = 0
    for line in source:
        lines += 1
    source.close()
    nb_mail=int(lines/5)
     
    source = open('outbox.txt', 'r')
    ligne = source.readlines()
     
    for i in range(0, nb_mail):
        from_addr=ligne[i*5]
        from_addr=from_addr[:len(from_addr)-1]
     
        to_addr=ligne[i*5+1]
        to_addr=to_addr[:len(to_addr)-1]
     
        sujet = ligne[i*5+2]
        sujet = sujet[:len(sujet)-1]
     
        body=ligne[i*5+3]    
        body = body[:len(body)-1]
     
        comm=ligne[i*5+4]    
     
        envoi_mail() # variable retour qui indique si le mail est parti ou pas
     
        if retour!='ok':
            source_temp = open("mail_temp.txt", "a")
            source_temp.write(from_addr+'\n')
            source_temp.write(to_addr+'\n')
            source_temp.write(sujet+'\n')
            source_temp.write(body+'\n')
            source_temp.write(comm)
            source_temp.close()
     
    source.close()
    subprocess.call('sudo cp mail_temp.txt outbox.txt', shell=True)
    subprocess.call('sudo rm mail_temp.txt', shell=True)
    A vous lire...

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dodineau Voir le message
    if os.path.exists('outbox.txt')==False:
    On ne compare pas avec True ou False parce que sont des valeurs réelles à la base (True=1 et False=0). Or il y a une différence entre "vérifier une vérité booléenne" et "comparer deux valeurs".
    Exemple: "toto" == True ou "toto" == False te donnera "False" dans les deux cas parce que littéralement parlant, "toto" n'est pas égal à 0 ou à 1. Alors que logiquement parlant, un des deux résultats devrait être "True" (le premier puisqu'une chaine non vide est considérée comme vraie).
    Une solution pourrait être le cast => bool("toto") == True là c'est ok mais le plus simple est de laisser l'évaluateur d'expression faire la conversion lui-même => if os.path.exists('outbox.txt'): ou bien if not os.path.exists('outbox.txt'):...

    Citation Envoyé par dodineau Voir le message
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    source = open('outbox.txt', 'r')
    lines = 0
    for line in source:
        lines += 1
    source.close()
    nb_mail=int(lines/5)
     
    source = open('outbox.txt', 'r')
    ligne = source.readlines()
    Pourquoi ouvrir le fichier 2 fois ? Déjà tu as source.seek() qui te permet de te replacer au début. Mais surtout tu n'as pas réalisé que "lines" c'était aussi la taille du tableau "ligne" ??? (et accessoirement essaye d'être plus original dans tes noms de variables)...

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    with open('outbox.txt', 'r') as source:
    	ligne = source.readlines()
    # with (le fichier est automatiquement fermé en fin de bloc "with")
    nb_mail=len(ligne)//5

    Citation Envoyé par dodineau Voir le message
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from_addr=ligne[i*5]
    from_addr=from_addr[:len(from_addr)-1]
     
    to_addr=ligne[i*5+1]
    to_addr=to_addr[:len(to_addr)-1]
     
    sujet = ligne[i*5+2]
    sujet = sujet[:len(sujet)-1]
     
    body=ligne[i*5+3]    
    body = body[:len(body)-1]
     
    comm=ligne[i*5+4]
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    (
    	from_addr,
    	to_addr,
    	sujet,
    	body,
    	comm,
    )=(x.replace("\n", "") for x in ligne[i*5:(i+1)*5])

    Citation Envoyé par dodineau Voir le message
    # variable retour qui indique si le mail est parti ou pas
    Variable globale ???

    Citation Envoyé par dodineau Voir le message
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    subprocess.call('sudo cp mail_temp.txt outbox.txt', shell=True)
    subprocess.call('sudo rm mail_temp.txt', shell=True)
    cp+rm=mv. Sinon tu travailles sous root ???
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Salut,

    Citation Envoyé par dodineau Voir le message
    Cette liste est composée de multiples de 5 lignes : expéditeur, destinataire, sujet, message, commentaires.
    Il n'y a aucune raison pour limiter "message" et "commentaires" à une seule ligne.

    Pour le reste, vous avez de bons tutos pour apprendre à programmer et vous permettre de créer un bien meilleur code....

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

  10. #10
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 334
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 334
    Par défaut
    Oui, très étrange d'avoir un "body" sur une ligne unique ... (A moins que ce n'est qu'un champ a remplacer dans un modèle)

    On ne peut pas dire que ton code s'inspire de ce qui a été répondu précédemment même pas strip() !
    donc pas la peine de proposer de précédemment une fonction de ce genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from collections import namedtuple
     
    Mail = namedtuple("sendMail", ["from_addr", "to_addr", "subject", "body", "com"])
     
    def read_by_five(filename):
        with open(filename,'rt') as f_read:
            try:
                while True:
                    lines = ()
                    for i in range(5):
                        lines += (next(f_read).rstrip(),)
                    yield Mail(*lines)
            except StopIteration:
                pass

  11. #11
    Membre confirmé Avatar de dodineau
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    100
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 100
    Par défaut
    Bonjour et merci pour vos réponses.
    Sve@r : Merci pour ces quelques précisions et les diverses optimisations de code.
    Variable globale, oui pourquoi ??

    wiztricks :
    Il n'y a aucune raison pour limiter "message" et "commentaires" à une seule ligne.
    Le fichier est créé par moi et les messages ne feront qu'une ligne et les commentaires ne feront qu'un mot.

    J'ai donc simplifié mon code grâce à vos remarques.

    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
     
    #!/usr/bin/python3
     
    import  sys
    import os, subprocess
     
    if not os.path.exists('outbox.txt'):
        print("Pas de fichier à traiter")
        sys.exit()
    #if
     
    subprocess.call('sudo cp outbox_0.txt outbox.txt', shell=True)
     
    with open('outbox.txt', 'r') as source:
        ligne = source.readlines()
    # with
    nb_mail=len(ligne)//5
     
    for i in range(0, nb_mail):
        (
            from_addr,
            to_addr,
            sujet,
            body,
            comm,
        )=(x.replace("\n", "") for x in ligne[i*5:(i+1)*5])
     
        envoi_mail() # variable retour qui indique si le mail est parti ou pas
        if retour!='ok':
            source_temp = open("mail_temp.txt", "a")
            source_temp.write(from_addr+'\n')
            source_temp.write(to_addr+'\n')
            source_temp.write(sujet+'\n')
            source_temp.write(body+'\n')
            source_temp.write(comm)
            source_temp.close()
     
    source.close()
     
    if not os.path.exists('mail_temp.txt'):
        subprocess.call('sudo rm outbox.txt', shell=True)
    else:
        subprocess.call('sudo mv mail_temp.txt outbox.txt', shell=True)
    A+

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dodineau Voir le message
    Variable globale, oui pourquoi ??
    Parce que c'est mal.

    Plus détaillé: les variables globales sont rarement une bonne idée. Certes elles offrent certains raccourcis mais dans 99% des cas ce sont des raccourcis inutiles (tu aurais défini ta fonction envoi_mail() comme renvoyant True/False selon que le mail soit bien/pas bien parti tu aurais pu écrire if envoi_mail() # La fonction indique si le mail est parti ou pas sans faire cette inutile comparaison de strings) et dans 95% des cas on le paye en retour de façon exponentielle.

    Déjà une variable globale casse la notion d'indépendance. Une fonction se veut généralement indépendante de son environnement. C'est à dire que si on lui passe les bons paramètres, elle doit pouvoir fonctionner dans différents programmes distincts et donner le bon résultat. Mais si la fonction a besoin d'une globale définie dans progA, elle ne pourra pas fonctionner dans progB sauf si le programmeurB pense à définir la même variable. Et puis que se passe-t-il si 2 fonctions utilisent un même nom pour leurs globales ? Ca t'aurait plu de ne pas pouvoir utiliser subprocess.call() parce que son créateur avait défini une variable "retour" du même nom ?

    Là encore on peut se dire que ce sont des détails mineurs. Mais quand tu commenceras à travailler en multithread, là ton truc explose en vol.

    Oui les globales existent parce que parfois on ne peut pas faire autrement. Mais ce "parfois" est très rarement atteint. Donc si tu peux éviter de tomber dans ce piège de la facilité...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Plus détaillé: les variables globales sont rarement une bonne idée.
    Certes mais les variables globales de Python n'ont rien de global.

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

  14. #14
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Certes mais les variables globales de Python n'ont rien de global.
    Peut-être que dans le détail interne Python les variables définies hors de l'espace local à une fonction ne sont pas des globales au sens littéral de la théorie des langages mais est ce que ça signifie que ce que j'ai dit est faux ? Ou que sa variable "retour" était une bonne idée ?
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  15. #15
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ou que sa variable "retour" était une bonne idée ?
    Savoir utiliser une fonction (et son retour) n'a rien à voir avec les variables globales "c'est mal".
    D'ailleurs je ne vois pas où envoi_mail est défini ni comment "retour" est assigné.

    En fait, les subprocess.call('sudo cp outbox_0.txt outbox.txt') me perturbent beaucoup plus. Je ne vois pas comment on peut lancer le script sans "sudo" et le module os a tout ce qu'il faut pour faire des copies.

    note: d'autant qu'in fine on se retrouve à installer Python, le système,... i.e. pourri l'environnement système à faire n'importe comment.

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

  16. #16
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Savoir utiliser une fonction (et son retour) n'a rien à voir avec les variables globales "c'est mal".
    Il ne sait pas (ou ne veut pas) utiliser le retour de la fonction comme test de réussite ou échec et par conséquent il passe par une variable globale pour communiquer cette information. Toutefois il se trouve qu'en règle générale utiliser des variables globale c'est mal parce que ... (tout ce que j'ai expliqué surtout la notion d'indépendance de la fonction vis à vis de l'environnement appelant)

    Citation Envoyé par wiztricks Voir le message
    D'ailleurs je ne vois pas où envoi_mail est défini ni comment "retour" est assigné.
    Il ne l'a pas montré mais personnellement je suis parti dans l'idée que c'était assigné de cette façon
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def envoi_mail():
    	global retour
    	if ... (travail envoi mail) réussi:
    		retour="OK"
    	else:
    		retour="KO"
    	# if
    # envoi_mail()
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  17. #17
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Toutefois il se trouve qu'en règle générale utiliser des variables globale c'est mal parce que ... (tout ce que j'ai expliqué surtout la notion d'indépendance de la fonction vis à vis de l'environnement appelant
    Je dis juste que concernant les fonctions il est préférable d'apprendre le mot clef return avant le mot clef global.

    Concernant les variables globales, si je fabrique un module avec dedans:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    a = 0
    def foo():
         global a
         a += 1
         print(a)
    On est bien d'accord que "a" est une variable globale.
    Maintenant, si je l'utilise ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    import module as m
     
    m.foo()
    print (m.a)
    On est bien d'accord que "a" n'est plus "variable globale" mais l'attribut d'un objet particulier.

    Si je veux fabriquer des variables globales avec Python, il faut créer un module "globs.py" et l'importer dans tous les autres modules de l'application. Et là on a effectivement créé variables globales et problèmes "potentiels" qui vont avec.

    Mais on n'y est pas encore.

    Sûr que si tous les accès à globs se font en lecture, il n'y a pas de soucis.
    Là ou çà se complique, c'est quand il y a des mises à jour.... mais pas tout de suite: si seule la fonction f met à jour a, et que seule la fonction g met à jour b,... çà reste gérable.

    Là où çà se complique, c'est lorsqu'on a des dépendances entre les variables i.e. a doit toujours être égal à -b, c doit toujours être égal à e + f.

    Et ce n'est qu'à ce niveau de complexité là qu'on comprend l'intérêt des "class": si a et b doivent vérifier a = -b, on les pousse dans la même "class", avec les fonctions qui les mettent à jour (ou plutôt une version plus light de celles ci) histoire de garantir la cohérence.
    Et aussi l'intérêt des setters/getters: tu veux a, je te retourne -b, tu veux modifier e, je recalcule c.

    Tu vois que çà va au delà de la simple utilisation du mot clef "global", d'autant que le gougnafier pourrait écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class globs:
         a = 0
    def foo():
         globs.a += 1
         print(globs.a)
    et voilà... pas vu pas pris.

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

  18. #18
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 875
    Billets dans le blog
    1
    Par défaut
    Jolie explication Il y a juste un détail avec lequel je ne suis pas d'accord (quand tu dis que comme les accès se font en lecture il n'y a pas de souci) parce que même si c'est vrai que la "non écriture" enlève certains soucis, le fait qu'une fonction utilise une variable externe nuit à son indépendance. Si ma fonction utilise une globale "a" même en lecture... mais que demain je remplace "a" par "nbSuperImportant" il faudra que je me recoltine tout mon code pour checker là où je l'utilise et ça je n'aime pas.

    Mais quoi qu'il en soit, j'ai bien aimé ton explication
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  19. #19
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    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 790
    Par défaut
    Salut,

    Citation Envoyé par Sve@r Voir le message
    Si ma fonction utilise une globale "a" même en lecture... mais que demain je remplace "a" par "nbSuperImportant" il faudra que je me recoltine tout mon code pour checker là où je l'utilise et ça je n'aime pas.
    Je suis d'accord: les fonctions "pures" sont bien plus sympathiques à maintenir.
    Malheureusement, il est un peu utopique d'écrire de vraies applications en "fonctionnel pur".

    Dans la pratique, dès qu'on écrit "import module" et qu'on utilise module.x, module.y,... on sera dépendant des attributs de module...
    x, y sont peut être des fonctions et le changement peut être sur les arguments plutôt que dans le nom.

    Si module est une bibliothèque externe, on devra faire attention aux montées de version, et si c'est une "class" ou un "module" qu'on a écrit, il faudra quand même faire attention aux bouts de code qui en dépendent.

    Mais il n'est pas nécessaire de prendre les mêmes précautions pour écrire un programme de quelques dizaines de lignes qui tient dans 2/3 scripts que pour un programme qui en fait/fera plusieurs milliers distribués en dizaines de packages/modules/class/...

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/03/2012, 12h09
  2. Tri fichier texte par bloc
    Par foubou dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 08/11/2008, 00h04
  3. lire un fichier texte par rapport à un symbole
    Par adeltimple dans le forum Langage
    Réponses: 3
    Dernier message: 26/05/2008, 23h14
  4. Réponses: 2
    Dernier message: 05/12/2005, 15h57

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