<jupyter_start><jupyter_text>[Entrée/Sortie fichier - File I/O](https://docs.python.org/3/tutorial/inputoutput.htmlreading-and-writing-files) [Vidéo d'aide](https://vimeo.com/484744700) Lire et écrire un fichier.**ATTENTION**: il est indispensable de *copier ce fichier* ainsi que le *répertoire* `donnees` dans un même lieu pour que tout fonctionne bien.  Travailler avec les chemins -*paths*- La forme exacte d'un chemin de fichier dépend du système d'exploitation utilisé. Sous windows, ils sont de la forme `c:\users\machin\monfichier.txt` et sous unix de la forme `/home/machin/monfichier.txt`.Pour écrire du code utilisant des chemins *indépendamment du système d'exploitation* sous-jacent, on utilise le module `path` du packet standard `os`:<jupyter_code>import os
fichier_courant = os.path.realpath('02_les_fichiers.ipynb')  
print(f'fichier courant: {fichier_courant}')
# Note: dans un fichier .py vous pouvez obtenir le nom du fichier courant
# avec la variable prédéfinie __file__ mais cela ne fonctionne pas dans un notebook
dossier_courant = os.path.dirname(fichier_courant) # ou  ...
# dossier_courant = os.getcwd() # pour «obtenir le current working directory»
print(f'dossier courant: {dossier_courant}')
# Note: dans un fichier .py vous pouvez obtenir le chemin du répertoire courant en utilisant os.path.dirname(__file__)
# construire des chemins
dossier_de_donnees = os.path.join(dossier_courant, 'donnees')
print(f'dossier de données: {dossier_de_donnees}')<jupyter_output><empty_output><jupyter_text>Vérifier qu'un chemin existe<jupyter_code>print(f'existe-t-il ? {os.path.exists(dossier_de_donnees)}')
print(f'est-ce un fichier ? {os.path.isfile(dossier_de_donnees)}')
print(f'est-ce un répertoire ? {os.path.isdir(dossier_de_donnees)}')<jupyter_output><empty_output><jupyter_text>Lire un fichier<jupyter_code>chemin_fichier = os.path.join(dossier_de_donnees, 'simple_fichier.txt')

with open(chemin_fichier, 'r') as simple_fichier:
    for ligne in simple_fichier:
        print(ligne.strip())<jupyter_output><empty_output><jupyter_text>La construction [`with`](https://docs.python.org/3/reference/compound_stmts.htmlthe-with-statement) sert à obtenir un manager de contexte -[context manager](https://docs.python.org/3/reference/datamodel.htmlwith-statement-context-managers)- qui sera utilisé comme un contexte d'exécution pour les commandes à l'intérieur du bloc `with`. Les managers de contextes garantissent qu'un certain nombre d'opérations seront réalisées lorsqu'on quitte le contexte. Dans ce cas, le manager de contexte garanti la fermeture du fichier - `simple_fichier.close()` est appelé implicitement - lorsqu'on sort du bloc de contexte. C'est une façon de simplifier la vie du développeur: vous n'avez pas à vous occuper de la fermeture du fichier ni de la survenue d'erreur à l'ouverture du fichier. Oublier de fermer un fichier peut conduire à de sérieux problèmes ... (c'est une ressource partagée).Ainsi, pour les entrées/sorties fichier, il est toujours préférable d'utiliser la *structure*: ```pythonwith open(...) as :    ```Pour vous donner un exemple, le même que précédemment sans le `with`:<jupyter_code>chemin_fichier = os.path.join(dossier_de_donnees, 'simple_fichier.txt')

# ÉVITER CETTE FAÇON DE FAIRE
simple_fichier = open(chemin_fichier, 'r')
for ligne in simple_fichier:
    print(ligne.strip())
simple_fichier.close()  # Nous sommes obligés de fermer le fichier explicitement<jupyter_output><empty_output><jupyter_text>Écrire dans un fichier<jupyter_code>nouveau_chemin_fichier = os.path.join(dossier_de_donnees, 'nouveau_fichier.txt')

with open(nouveau_chemin_fichier, 'w') as mon_fichier:
    mon_fichier.write("C'est le premier fichier que j'écris avec Python.")<jupyter_output><empty_output><jupyter_text>Après ça, assurez-vous qu'un fichier 'nouveau_fichier.txt' se trouve dans le dossier de données. Pour le supprimer:<jupyter_code>if os.path.exists(nouveau_chemin_fichier):  # assurons-nous qu'il est bien présent.
    os.remove(nouveau_chemin_fichier)<jupyter_output><empty_output><jupyter_text>Exercices<jupyter_code># ÉXÉCUTER CETTE CELLULE AVANT TOUT!

# Constantes pour les exercices:
REPERTOIRE_COURANT = os.getcwd()
REPERTOIRE_DONNEES = os.path.join(REPERTOIRE_COURANT, 'donnees')<jupyter_output><empty_output><jupyter_text>1. Ajouter des nombres contenus dans un fichierCompléter les parties manquantes  ____  du code qui suit. La fonction `somme_nombres_dans_fichier` prend un chemin de fichier en argument, lis les nombres qu'il contient ligne à ligne et retourne la somme de ces nombres. Vous pouvez supposer que chaque ligne contient exactement un valeur numérique.<jupyter_code>def somme_nombres_dans_fichier(chemin_fichier):
    sum_ = 0  # Astuce: un moyen courant d'utiliser une variable en conflit avec un nom prédéfini
              #  est de le faire suivre d'un caractère de soulignement _ (underscore)
    with ____(chemin_fichier, ____) as ____:
        for ligne in ____:
            ____ = ligne.strip()  # Supprimer des caractères «blancs» éventuels 
            ____ += float(____)   # conversion str -> float
    return ____
fichier_nombres = os.path.join(REPERTOIRE_DONNEES, 'nombres.txt')
assert somme_nombres_dans_fichier(fichier_nombres) == 189.5<jupyter_output><empty_output><jupyter_text>Solution<jupyter_code>def somme_nombres_dans_fichier(chemin_fichier):
    sum_ = 0  # Astuce: un moyen courant d'utiliser une variable en conflit avec un nom prédéfini
              #  est de le faire suivre d'un caractère de soulignement _ (underscore)
    with open(chemin_fichier, 'r') as le_fichier:
        for ligne in le_fichier:
            chaine_nb = ligne.strip()  # Supprimer des caractères «blancs» éventuels 
            sum_ += float(chaine_nb)   # conversion str -> float
    return sum_<jupyter_output><empty_output><jupyter_text>2. Lire le premier mot de chaque ligne d'un fichierImplémenter la fonction `trouver_premier_mots` qui prend un chemin de fichier en argument. La fonction devrait trouver le premier mot de chaque ligne du fichier et retourner ces mots dans une liste. Si une ligne est vide, la liste devrait contenir une chaîne vide pour cette ligne.<jupyter_code># À toi de jouer!
fichier_1 = os.path.join(REPERTOIRE_DONNEES, 'simple_fichier.txt')
fichier_2 = os.path.join(REPERTOIRE_DONNEES, 'simple_fichier_avec_des_lignes_vides.txt')

attendu_pour_fichier_1 = ['Première', 'Deuxième', 'Troisième', 'Et']
assert trouver_premier_mots(fichier_1) == attendu_pour_fichier_1

attendu_pour_fichier_2 = ['Le', '', 'Premier', 'sans', '', 'Puis']
assert trouver_premier_mots(fichier_2) == attendu_pour_fichier_2<jupyter_output><empty_output><jupyter_text>Solution<jupyter_code>def trouver_premier_mots(chemin_fichier):
    liste_a_retourner = []
    with open(chemin_fichier, 'r') as le_fichier:
        for ligne in le_fichier:
            mots = ligne.split()
            if len(mots) != 0:
                premier_mot = mots[0]
            else:
                premier_mot = ''
            liste_a_retourner.append(premier_mot)
    return liste_a_retourner<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09153640332347557, 'fraction_numerical': 0.004506407548232643, 'mean_word_length': 5.284955752212389, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 47, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '203571', 'license': 'CC0-1.0', 'n_tokens_mistral': 2681, 'n_tokens_neox': 2666, 'n_words': 650, 'path': '00_bases_python/complements/02_les_fichiers.ipynb', 'repo_name': 'efloti/cours-nsi-premiere', 'size': '7101'}