Annonce

Réduire
Aucune annonce.

Les fichiers - COURS N°6

Réduire
Ceci est une discussion importante.
X
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Tutoriel Les fichiers - COURS N°6

    Bonjour,

    À savoir : Ce tutoriel risque d'être modifié, changé de place, voir même supprimé selon les décisions de l'équipe hackademics. Sa présence, est dû aux attentes des membres du forum participant au cours Python.

    Tout conseils, modifications à votre demande, sera envoyé par MP.

    Aucune réponse ne sera donnée dans ce post, seule les questions d'incompréhension du tutoriel seront acceptées.

    LES FICHIERS

    Toutes les informations dans nos programmes étaient créées de façon temporaire, soit en dure par le programmeur, soit par l'utilisateur.

    Si je voulais créer un programme gérant un carnet d'adresses, il est bien évident que je ne pourrais ni rentrer en dur toutes les adresses dans mon programme, ni demander à l'utilisateur de rentrer à chaque fois toutes les adresses.

    Pour nous donner ce moyen de stocker (persistance de l'information) ces adresses de manière permanente, les fichiers sont le moyen parfait.

    PROBLÉMATIQUE

    Coder un programme permettant la gestion d'un carnet d'adresse sous cette forme

    NOM;PRENOM;ADRESSE;TÉLÉPHONE

    Cette structure est dite délimitée, notre caractère de délimitation est le ';'

    Les fonctions suivantes seront présentes:
    • ajouter
    • effacer
    • modifier


    ajouter -> Pour ajouter une adresse
    effacer -> Pour effacer une adresse
    modifier -> Pour modifier une adresse

    Elles feront donc partie du menu à présenter à l'utilisateur...

    image_1.jpg

    Pour ajouter une adresse, on demandera les informations suivantes:
    • Votre nom
    • Votre prénom
    • Votre adresse
    • Votre téléphone


    image_2.jpg

    Il faudra ensuite l'enregistrer dans un fichier en faisant bien attention de ne pas supprimer les autres adresses.

    Pour cela un plan s'impose
    1. Les différents mode d'ouverture
    2. Lire un fichier
    3. Écrire dans un fichier



    I) LES DIFFÉRENTS MODE D'OUVERTURE

    Pour ouvrir un fichier avec un mode prédéfini

    Code:
    with open('Carnet.txt', mode) as f:
    with open ? je croyais que c'était open ? En effet on peut utiliser open, mais with open a un avantage que la doc indique clairement.

    Envoyé par doc officielle
    It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way. It is also much shorter than writing equivalent try-finally blocks
    Votre fichier à l'aide de with open sera proprement fermé, plus la peine de penser à le fermer. De plus il évite de tester si le fichier existe avec des blocs try-except-finally (on verra un peu plus tard).

    Il existe 3 modes essentiels rendant complet le travail sur les fichiers.
    1. Le mode r
    2. Le mode w
    3. Le mode a


    Le mode r

    Il permet de lire (read) un fichier de données brutes (notre cas ici)

    Code:
    with open('Carnet.txt', 'r') as f:
    Le mode w

    Il permet d'écrire (write) depuis le début d'un fichier, c'est à dire que si un fichier est déjà avec des lignes inscrites, elles seront tout simplement supprimées du fichier. Attention!

    Code:
    with open('Carnet.txt', 'w') as f:
    Le mode a

    Il permet d'ajouter (append) des lignes dans le fichier, on se retrouvera donc en fin de fichier.

    Code:
    with open('Carnet.txt', 'a') as f:
    II) LIRE UN FICHIER

    Comme dis précédemment, on utilise with open pour ouvrir un fichier

    Pour lire les lignes d'un fichier, c'est une boucle for que l'on aura besoin.

    Code:
    with open('Carnet.txt', 'r') as f:
        for line in f:
            print(line)
    Qui se traduit par

    Code:
    Ouvrir fichier en mode read que j'appelle f
        Pour chaque ligne du fichier:
            afficher ligne
    Comme vous pouvez le remarquer with open est un bloc (se termine par ':'), il ne faut pas oublier l'indentation par la suite.

    III) ÉCRIRE DANS UN FICHIER

    Idem nous devons ouvrir le fichier, mais le mode change, soit en mode 'w' ou 'a'.

    On utilise la méthode write pour écrire dans un fichier.

    Code:
    with open('Carnet.txt', 'w') as f:
        f.write('nom; prenom; adresse; telephone')
    Qui se traduit par

    Code:
    Ouvrir fichier en mode write que j'appelle f (création d'un nouveau fichier)
        écrire ligne
    EXERCICES


    1) Résoudre la problématique
    2) Créer un jeu du plus ou moins où vous enregistrerez un score (représentant le nombre de tentatives pour trouver le nombre mystère)

    PSEUDO_1 -> score_1
    PSEUDO_2 -> score_2

    Il faut qu'il soit placé dans l'ordre, du plus grand score au plus petit.

    Vous pouvez éventuellement utiliser sorted et son paramètre key, voir la doc

    Aide à l'analyse des paramètres à prendre en compte.

    Exemple d'application

    python3 monfichier.py fichier.txt

    Ci-dessus la ligne à parser (analyser), pour cela on utilise argv du module sys

    On l'appelle comme cela

    Code:
    import sys
    
    print(sys.argv) # retourne la liste des paramètres
    Si on teste avec notre ligne

    Code:
    [email protected]:~/Desktop$ python3 parse.py fichier.txt
    ['parse.py', 'fichier.txt']
    On remarque que nos paramètres sont:
    • Le nom du fichier qu'on exécute
    • Le nom du paramètre ajouté lors de l'exécution


    sys.argv est donc une liste

    Vérifier qu'on a un seul argument veut donc dire qu'au total nous avons 2 arguments
    • Le nom du fichier (incontournable)
    • Le paramètre



    Pour vérifier, il suffit de démontrer que nous avons 2 arguments

    Code:
    import sys
    
    print(len(sys.argv))
    Code:
    [email protected]1599-Aspire-5741G:~/Desktop$ python3 parse.py fichier.txt
    2
    Maintenant on peut annoncer quitter le programme, si on a plus ou moins de 2 arguments avec la fonction exit du module sys

    Code:
    import sys
    
    if len(sys.argv) != 2:
        sys.exit("one argument please!")
    Code:
    [email protected]:~/Desktop$ python3 parse.py
    one argument please!
    Maintenant faut vérifier que notre fichier existe, c'est mieux non?

    os.path.exists est notre ami

    On l'appelle de cette façon

    Code:
    import os.path
    Du coup un petit test

    Code:
    param = sys.argv[1] # je prend mon paramètre fichier.txt
    if os.path.exists(param):
        print("{} existe!".format(param))
    Code:
    [email protected]:~/Desktop$ python3 parse.py test.txt
    test.txt existe!
    Si le fichier n'existe pas, il faut lui annoncer en quittant comme une brute notre programme...

    Code:
    param = sys.argv[1] # je prend mon paramètre fichier.txt
    if os.path.exists(param):
        print("{} existe!".format(param))
    else:
        sys.exit("no file existing for {}".format(param))
    Code:
    [email protected]:~/Desktop$ python3 parse.py test.py
    no file existing for test.py
    Sous la demande de quelques membres, je rajoute des exercices plus simples, ça ajoutera des acquis supplémentaires dans le thème "Entrées-Sorties"

    Exercice 1:

    Ecrivez un programme qui prend un fichier texte en argument de la ligne de commande et affiche le nombre de mots dans le fichier.

    La ligne de commande, c'est par exemple: python mon_fichier.py argument

    Pour lire l'argument depuis une ligne de commande, il vous faut argv du module sys, dont voici un exemple d'utilisation...

    1) Parser la ligne de commande pour en ressortir le fichier, on peut par exemple créer une fonction parse_command, qui permettrait de retourner une erreur dans des cas spécifiques non appropriés (pas assez d'arguments, ...)
    2) Vérifier que le fichier existe os.path, on pourrait placer cette vérification dans la fonction parse_command.
    3) Créer une fonction parse(line) qui analysera votre ligne et retournera le nombre de mots.

    En ressortir tous les mots en prenant en compte la ponctuation

    Code:
    >>> from string import punctuation
    >>> punctuation
    '!"#$%&\'()*+,-./:;<=>[email protected][\\]^_`{|}~'
    Le résultat sera :

    Code:
    print(parse("Bonjour, comment ça va?")) # il y a 4 mots
    4
    4) Créer une fonction parse_all(file) qui analysera le fichier et où vous utiliserez la fonction parse pour chacune des lignes du fichier et retournera le nombre de mots total.

    5) Afficher le nombre de mots

    Exercice 2:

    Ecrivez un programme qui prend un fichier texte et un mot en argument de la ligne de commande et affiche le nombre d'occurrences du mot dans le fichier.

    Vous pourriez utiliser count, mais ça serait bien trop simple

    Je vous demande de réfléchir à un algorithme permettant de compter le nombre de mots identique dans un texte.

    Pour cela l'exercice 1 peut vous aider...

    Voilà j'en dis pas plus je vous laisse avec votre 1ère réflexion sur le projet

    Dans le cadre actuel, je préfère l'envoi des codes en MP, je renverrais une fois tous les codes donnés sur un post toutes vos solutions en vous nommant.

    Ça évite d'être influencé par un code, voir mal influencé...

    Merci
    Dernière modification par SAKAROV, 17 juin 2013, 03h16.

  • #2
    Bonjour,

    Merci pour ce tuto, je suis entrain de faire les exercices.

    Pour le jeu du plus moins, j'ai une question.
    Est ce vraiment intéressant d'utiliser sorted? Car ca nécessite de recharger tout le fichier.

    Le code suivant me semble plus efficace non? :
    Code:
    with open('score.txt', 'r') as f:
    	is_done = False
    	for line in f:
    		mon_tuple = ()
    		mon_tuple = line.split(';') # Récupération de chaque ligne
    		if(int(mon_tuple[0]) > count and is_done == False):
    			writeInFile((count, firstname, lastname), 'tmp.txt')
    			writeInFile(mon_tuple, 'tmp.txt')
    			is_done = True
    		else:
    			writeInFile(mon_tuple, 'tmp.txt')
    	
    	if is_done != True:
    		writeInFile((count, firstname, lastname), 'tmp.txt')
    
    os.rename('tmp.txt', 'score.txt')
    Merci pour votre aide dans ma compréhension

    Commentaire


    • #3
      sorted permet d'ordonner des valeurs à partir d'un itérable tel que la liste par exemple, je ne vois pas le rapport avec le chargement d'un fichier, si toutes tes valeurs lues dans le fichier sont ajoutées dans une liste...

      Commentaire


      • #4
        Justement, si toutes les valeurs lues dans ton fichier sont ajoutées à une liste, si le fichier est gros, c'est pas top niveau mémoire non?

        Commentaire


        • #5
          La méthode avec sorted semble plus élégante.

          @Back2Back, ton code semble beaucoup plus gourmand en écriture et lecture sur le fichier, tandis qu'avec sorted, tu récupères toutes tes valeurs, les tries, et tu balances

          le résultat dans le fichier. En plus, bien que ton code place le meilleur score correctement, la ligné ajoutée écrase celle existante et supprime un score donc ?
          deux et deux font cinq

          Commentaire


          • #6

            Justement, si toutes les valeurs lues dans ton fichier sont ajoutées à une liste, si le fichier est gros, c'est pas top niveau mémoire non?
            Ajouter dans une liste est en O(1), ce qui n'est absolument pas coûteux... et est donc négligeable par rapport à la lecture ligne par ligne d'un fichier.

            Mais je n'aime pas trop discuter d'un code quand je n'ai pas les tenants et les aboutissants. Pour moi la fonction la plus importante de ton code est writeInFile qui me semble bien trop répétitive quand à son utilisation... et qui pourrait être une fonction coûteuse. Peut-être est-ce la conséquence de ta question d'origine ?

            Niveau syntaxe je vois des choses à modifier, mais j'ai pas le temps de voir ça aujourd'hui, peut-être demain !

            Commentaire


            • #7
              Envoyé par shirocen Voir le message
              La méthode avec sorted semble plus élégante.

              @Back2Back, ton code semble beaucoup plus gourmand en écriture et lecture sur le fichier, tandis qu'avec sorted, tu récupères toutes tes valeurs, les tries, et tu balances

              le résultat dans le fichier. En plus, bien que ton code place le meilleur score correctement, la ligné ajoutée écrase celle existante et supprime un score donc ?
              Merci pour ta réponse. Non je n'écrase aucune ligne car je stocke dans un fichier temporaire.

              Envoyé par fred Voir le message
              Ajouter dans une liste est en O(1), ce qui n'est absolument pas coûteux... et est donc négligeable par rapport à la lecture ligne par ligne d'un fichier.

              Mais je n'aime pas trop discuter d'un code quand je n'ai pas les tenants et les aboutissants. Pour moi la fonction la plus importante de ton code est writeInFile qui me semble bien trop répétitive quand à son utilisation... et qui pourrait être une fonction coûteuse. Peut-être est-ce la conséquence de ta question d'origine ?

              Niveau syntaxe je vois des choses à modifier, mais j'ai pas le temps de voir ça aujourd'hui, peut-être demain !
              Effectivement, vous avez raison, je n'y ai pas pensé, mais travailler sur des fichiers est plus couteux en ressources. Autant pour moi. Dsl pour cette question idiote :/

              Commentaire


              • #8
                Dsl pour cette question idiote
                La question n'est pas idiote à partir du moment où on apprend quelque chose...

                Voici quelques ressources supplémentaires,

                En ce qui concerne la syntaxe,

                Initialisation inutile

                Code:
                mon_tuple = ()
                mon_tuple = line.split(';') # Récupération de chaque ligne
                Pas besoin d'initialiser mon_tuple, qui puis est la réponse de python à la méthode split est un objet de type list.

                donc quelque chose du genre ci-dessous est plus adapté,

                Code:
                infos_user = line.split(';')
                Mieux vaut simple que complexe

                Code:
                if(int(mon_tuple[0]) > count and is_done == False):
                    writeInFile((count, firstname, lastname), 'tmp.txt')
                    writeInFile(mon_tuple, 'tmp.txt')
                    is_done = True
                else:
                    writeInFile(mon_tuple, 'tmp.txt')
                C'est trop compliqué, je ne connais pas writeInFile, mais dans ton fichier final, le tri ne doit pas modifier la forme de départ du fichier à lire. Est-ce ça fait bien cela ? Je ne sais pas... je n'ai pas tout les éléments.

                Sémantique

                Code:
                if is_done != True:
                Plus sémantique et idiomatique en python est

                Code:
                if not is_done:
                Voilà pour résumer le petit bout de code niveau syntaxe

                Commentaire


                • #9
                  Envoyé par fred Voir le message
                  Initialisation inutile

                  Code:
                  mon_tuple = ()
                  mon_tuple = line.split(';') # Récupération de chaque ligne
                  Pas besoin d'initialiser mon_tuple, qui puis est la réponse de python à la méthode split est un objet de type list.

                  donc quelque chose du genre ci-dessous est plus adapté,

                  Code:
                  infos_user = line.split(';')
                  Merci, effectivement, habitude de dev C ahah

                  Envoyé par fred Voir le message
                  Mieux vaut simple que complexe

                  Code:
                  if(int(mon_tuple[0]) > count and is_done == False):
                      writeInFile((count, firstname, lastname), 'tmp.txt')
                      writeInFile(mon_tuple, 'tmp.txt')
                      is_done = True
                  else:
                      writeInFile(mon_tuple, 'tmp.txt')
                  C'est trop compliqué, je ne connais pas writeInFile, mais dans ton fichier final, le tri ne doit pas modifier la forme de départ du fichier à lire. Est-ce ça fait bien cela ? Je ne sais pas... je n'ai pas tout les éléments.
                  writeInFile ne fait que écrire les informations envoyées dans le fichier, mais je ne crois pas qu'elle modifie la forme de départ.
                  Voici mon GitHub si tu veux jeter un coup d'oeil à la fonction writeInFile : https://github.com/MThibault/HK_Python

                  Envoyé par fred Voir le message
                  Sémantique

                  Code:
                  if is_done != True:
                  Plus sémantique et idiomatique en python est

                  Code:
                  if not is_done:
                  Voilà pour résumer le petit bout de code niveau syntaxe
                  Corrigé aussi, merci pour tes retours

                  Commentaire

                  Chargement...
                  X