9. Les entrées-sorties (E/S) : formats#

Partie Programmation

Mis à jour : May 15, 2025, lecture : 7 minutes minimum, PhL.

Ce chapitre complète le chapitre “Entrées-sorties avec des fichiers”.
On y présente comment peaufiner le format ses entrées-sorties à l’écran ou dans des fichiers de texte.

9.1. Les formats d’écriture, de lecture et d’affichage#

Il s’agit de définir la façon dont s’écrivent, se lisent ou s’affichent à l’écran les informations textuelles, i.e. les chaînes de caractères.
Exemple : combien de chiffres après la virgule d’un float, utiliser une notation scientifique (\(\pm 1.xxxx \cdot 10^E\)), insérer ou non des caractères avant la str à afficher, …

On commence par la syntaxe qui permet d’exprimer le formatage voulu (syntaxe un peu lourde au début), puis on montre deux moyens d’appliquer l’opération de formatage : les chaînes formatées (ou f-string en python) puis la méthode plus générale .format (méthode définie pour les str).

Ces formats d’affichage s’appliquent aux chaînes de caractères utiles aux entrées-sorties textuelles (avec print() pour l’écran, mais aussi write() et read() pour les fichiers de texte).

9.1.1. Spécifier le format de nombres et des chaînes de caractères#

La syntaxe générale d’un format (d’écriture ou d’affichage) est :

:[drapeau][largeur][.precision][type]

Après le symbole :, chacun des 4 champs est optionnel.

  • [drapeau] contrôle la justification de la valeur par :

    • un caractère de remplissage (optionnel) : .,*,-, …

    • et sa position : centré :^, aligné à gauche : <, à droite : >

  • [largeur] : la largeur de l’écriture (en nombre de caractères)

  • [.precision] : le nombre de chiffres après la virgule . pour les nombres flottants

  • [type]: le paramètre le plus important qui dépend du type de la valeur et décrit un mode général de représentation.

Une valeur de format est aussi appelée code de format par la littérature python.

Rmq. importante Les exemples qui suivent pour illustrer l’effet de ces codes sont donnés :

  • sur l’affichage à l’écran par print(),

    • un effet identique est obtenu par des read() ou des write() dans les fichiers;

  • d’une chaîne formatée ou aussi f-string) : c’est une forme de chaine de caractères

    • reconnaissable par le fou F qui précède le "ou le ' d’ouverture de chaîne,

    • et qui sera détaillée dans la section suivante.

On a indiqué que [type]est le paramètre de format le plus important en pratique. C’est donc lui qui guide la présentation.

Formatage de nombres int#

Le champs [type]peut prendre les valeurs d (par défaut), x, X, o, et b dont le sens est illustré par les 5 codes suivants.

type

code (str)

format

int

{0:d}

entier en base 10 (décimal) (par défaut)

int

{0:x}

entier en base 16 (hexa-décimal) en minuscules

int

{0:X}

entier en base 16 (hexa-décimal) en majuscules

int

{0:o}

entier en base 8 (octal)

int

{0:b}

entier en base 2 (binaire)

Rmq. Ne pas se soucier du ‘0’ avant le ‘:’ qui débute le format.

print("22")
print(f"{22:d}")
print(f"{22:x}")
print(f"{22:X}")
print(f"{22:o}") 
print(f"{22:b}")
22
22
16
16
26
10110

On verra avec la présentation des chaînes formatée qu’on peut formater des expressions évaluées à l’exécution – mais toujours comme des chaînes de caractères.

Le traitement suivant est similaire au précédent en introduisant une variable var à (la valeur de) laquelle s’applique le formatage.

var = 22
print(var)
print(f"{var:d}")
print(f"{var:x}")
print(f"{var:X}")
print(f"{var:o}")
print(f"{var:b}")
22
22
16
16
26
10110

On illustre brièvement l’effet des champs [position] et [largeur] sur des décimaux.

var = 22
print(var, ": format par défaut du print")
print(f"{var:10d}", ": sur 10 caractères, alignement à droite par défaut pour 'int'")
print(f"{var:-^10d}", ": centré sur 10 caractères")
print(f"{var:.<10d}", ": aligné à gauche, 10 caractères complétés par des .")
22 : format par défaut du print
        22 : sur 10 caractères, alignement à droite par défaut pour 'int'
----22---- : centré sur 10 caractères
22........ : aligné à gauche, 10 caractères complétés par des .

Les écritures classiques des entiers sont aussi obtenues à l’aide des codes suivants.

type

code (str)

format

int

{0:+d}

entier en base 10 avec signe + explicite

int

{0:0=nb}

entier en base 10 écrit avec nb chiffres, complétés de 0 si besoin

int

{0:#x}

entier en base 16 avec #

int

{0:#o}

entier en base 8 avec o

int

{0:#b}

entier en base 2 avec b

var = 22
print(f"{var:+d}")
print(f"{var:0=4}")
print(f"{var:#X}")
print(f"{var:#o}")
print(f"{var:#b}")
+22
0022
0X16
0o26
0b10110

Formatage de nombres float#

Le champs [type] peut prendre les valeurs f, e, g et %.

Avec les champs [drapeau], [largeur] et [précision], on obtient des formats adaptés aux float.

type

code (str)

format

float

{0:2.4f}

2 chiffres avant la virgule et 4 après

float

{0:.5e}

notation scientifique avec 5 chiffres après la virgule

float

{0:g}

un format générique “qui va bien”

float

{0:.2%}

pourcentage avec 2 décimales

from math import pi as pi
print("pi=", pi)
print(f"{pi:2.3f}")
print(f"{pi:+.5e}")
print(f"{pi:g}")
print(f"{pi:*^+15.5e}")
pi= 3.141592653589793
3.142
+3.14159e+00
3.14159
*+3.14159e+00**

Rmq. Ces formatages d’int et de float apparaissent aussi dans d’autres langages de programmation, e.g. C.

Formatages de chaînes de caractères#

Dans ce cas, on défini les champs drapeau et largeur comme déjà indiqué.

type

code (str)

format

str

{:nb}

chaîne justifiée à gauche sur nb caractères (complétée d’espaces à droite si besoin)

str

{:>nb}

chaîne justifiée à droite sur nb caractères (complétée d’espaces à gauche si besoin)

str

{:^nb}

chaîne centrée sur nb caractères (complétée d’espaces si besoin)

str

{:-^nb}

chaîne centrée sur nb caractères, complétée de - si besoin

str

{:.<nb}

chaîne justifiée à gauche sur nb caractères, complétée de . à droite si besoin

s = "un texte formaté"
print(len(s))
print(f"{s:35}")
print(f"{s:>35}")
print(f"{s:^35}")
print(f"{s:+^35}")
16
un texte formaté                   
                   un texte formaté
         un texte formaté          
+++++++++un texte formaté++++++++++

Les caractères spéciaux \... #

On rappelle que les caractères spéciaux ou séquences d’échappement sont l’association du “backslash” \ et de certains symboles (ou suite de symboles). Cette suite de caractères (qui commence par \) est interprétée de façon particulière.

Caractères spéciaux “de contrôle”:

  • \b : backspace

  • \t \v: tabulation horizontale ou verticale

  • \n : new line saut de ligne

  • \f : form feed saut de page

  • \r : retour en début de ligne

On a vu que le \ évite d’évaluer “normalement” le symbole qui le suit.

Donc :

  • \\ s’évalue comme le caractère \,

  • \' ou \" ou \/ comme les symboles ' ou " ou /

  • et \\n comme la chaîne de 2 caractères non évalués \n.

Retenons que \ permet de ne pas interpréter avec le sens réservé par les choix du langage de programmation le caractère qui le suit. Il ramène au caractère ou à la chaîne de caractère écrites – et non son interprétation. Cette notion se retrouve dans d’autres langages de programmation : C, …

Des fonctions plus générales qui résolvent ce type de problème sont présentées comme compléments en fin de chapitre.

print(“a\nb”)

9.1.2. Les expressions ou chaînes formatées#

Principe

  1. On définit un format d’affichage pour une chaîne de caractères qui dépend de la valeur de certains champs à formater

  2. On applique ce format à un nombre arbitraire de valeurs

  3. On obtient un nombre arbitraire de valeurs affichées de la même manière.

Syntaxe :

f"une chaine de caractères qui contient au moins un {champs à formater}"

quantieme = 12
mois = "mars"
annee = 2021
temp = 18.2
s = f"La température du {quantieme} {mois} {annee} est {temp}oC."
print(s)
La température du 12 mars 2021 est 18.2oC.

L’intérêt de ces expressions (ou chaînes) formatées est mis en valeur en introduisant les formats d’affichage vus précédemment pour chaque champs et le type de valeur attendu.

Ces formats d’affichage commencent ici après le : de chaque champs de l’expression formatée.

quantieme = 4
mois = 'mars'
annee = 2021
temp = 18.2
s1 = f"La température du {quantieme:2d} {mois:^10} {annee} est {temp:2.1f}oC."
# un entier sur 2 chiffres décimaux, 
# une chaine centrée sur 10 caractères,
# un nombre flottant avec au plus 2 chiffres significatifs et une décimale

quantieme = 12
mois = 'janvier'
annee = 2021
temp = 5.58
s2 = f"La température du {quantieme:2d} {mois:^10} {annee} est {temp:2.1f}oC." 

print(s1)
print(s2)
La température du  4    mars    2021 est 18.2oC.
La température du 12  janvier   2021 est 5.6oC.

9.1.3. La méthode .format().#

L’exemple précédent donne envie de pouvoir définir une fois pour toute l’expression formatée et de pouvoir l’appliquer à un nombre arbitraire de valeurs pour obtenir l’affichage formatée de ces valeurs.

C’est l’objet de la méthode .format() qui s’applique à des str.

La syntaxe de .format() est un peu déroutante au début.

st_format.format(arg) retourne une chaîne de caractères str formatée

  • st_format est une chaine de caractères qui définit le format d’affichage voulu : similaire à l’expression formatée, elle contient les champs délimitées par des { } qui intégrent éventuellement des spécifications de format.

  • arg est un conteneur tuple ou dict ou str de valeurs à formater.

Ainsi st_format.format(arg) applique à arg, les traitements définies entre { } de la chaîne de définition du format st_format.

Rmq.

  • Cette construction permet de définir “une fois pour toute” la chaîne st_format puis de l’appliquer à un nombre arbitraire d’arg – ce qui n’est pas possible avec les expressions formatées f-strings.

  • On rappelle que le type str est non-mutable – ce qui nous fait souvent préférer la dénomination expression formatée plutôt que chaîne formatée, traduction rapide du jargon python f-string.

Exemple. Une météo hasardeuse.

import random

le_format = "La température du {:2d} {:^10} {} est {:+5.1f} oC."

a = 2021
for m in ('janvier','février','mars'):
    for q in range(1,28,4):
        t = random.uniform(-2.0,15.9)
        s = le_format.format(q, m, a, t)
        print(s)
        
La température du  1  janvier   2021 est  +3.9 oC.
La température du  5  janvier   2021 est  +2.3 oC.
La température du  9  janvier   2021 est  +8.3 oC.
La température du 13  janvier   2021 est +10.1 oC.
La température du 17  janvier   2021 est  +7.2 oC.
La température du 21  janvier   2021 est  +1.8 oC.
La température du 25  janvier   2021 est +12.6 oC.
La température du  1  février   2021 est  +1.6 oC.
La température du  5  février   2021 est  +6.3 oC.
La température du  9  février   2021 est  +7.5 oC.
La température du 13  février   2021 est  +0.9 oC.
La température du 17  février   2021 est  +0.5 oC.
La température du 21  février   2021 est  +4.6 oC.
La température du 25  février   2021 est +14.1 oC.
La température du  1    mars    2021 est  +1.5 oC.
La température du  5    mars    2021 est  +7.2 oC.
La température du  9    mars    2021 est  -1.1 oC.
La température du 13    mars    2021 est  -1.7 oC.
La température du 17    mars    2021 est +11.0 oC.
La température du 21    mars    2021 est  +1.2 oC.
La température du 25    mars    2021 est +14.2 oC.

Le formatage de données textuelles s’applique aussi aux E-S sur fichiers.

Il est classique de mentionner que la méthode .format() permet aussi d’effectuer des substitutions (des remplacements) de certaines parties de chaînes de caractères.

# formatage avec remplacement par st
le_format =  "Le {} mot est {} {}"
st_formatee = le_format.format("premier", "très important", "....")

# affichage
print(st_formatee)
print(le_format)

# ecriture fichier
st1 = "capital, "
st2 = "assurément"
with open("./tmp/format1.txt", "w", encoding="utf8") as f:
    f.write(st_formatee)
    f.write("\n")    
    f.write(le_format.format("dernier", st1 + st2, "!"))
    f.close()
Le premier mot est très important ....
Le {} mot est {} {}
!cat tmp/format1.txt 
Le premier mot est très important ....
Le dernier mot est capital, assurément !

Rmq. Il est commode de voir la chaîne st_format comme un masque de mise en forme qui va s’appliquer aux valeurs de l’argument arg. Cette utilisation par remplacement peut faire penser (à tort) à un rôle inversé de l’argument à formater arg et de la chaîne st_format qui définit le formatage. Ce risque de confusion sera levée avec l’étude de la programmation objet (en python) – hors du programme de ce semestre.

9.1.4. (\(\star\)) Compléments#

Objectif 20 et en seconde lecture

str() et repr()#

Vous avez utilisé –de façon explicite ou “à votre insu”– la fonction str() pour convertir une valeur de type quelconque en sa représentation comme une chaîne de caractères.

  • Citez un exemple d’utilisation implicite de str()

La fonction str() donne accès à la chaîne de caractères argument interprétée.

La fonction repr() donne accès à la chaîne de caractères argument sans l’interpréter.

val = 22
s = str(val)
r = repr(val)
print(val, s, r, sep="*")
print(type(val), type(s), type(r))
print()

val = "\n"
s = str(val)
r = repr(val)
print(val, s, r, sep="*")
print(type(val), type(s), type(r))
print()

val = "\\n"
s = str(val)
r = repr(val)
print(val, s, r, sep="*")
print(type(val), type(s), type(r))
22*22*22
<class 'int'> <class 'str'> <class 'str'>


*
*'\n'
<class 'str'> <class 'str'> <class 'str'>

\n*\n*'\\n'
<class 'str'> <class 'str'> <class 'str'>

Lorsqu’aucun formatage particulier n’est souhaité, ces fonctions peuvent être utilisées avec les raccourcis suivants qui complètent les champs {} des f-strings ou du formatage de .format().

  • !s pour str()

  • !r pour repr()

  • !a pour ascii()

mr_ou_mme = "Madame, \n Monsieur."
hello_s = f"Bonjour {mr_ou_mme!s}"
hello_r = f"Bonjour {mr_ou_mme!r}"
hello_a = f"Bonjour {mr_ou_mme!a}"
print(hello_s, hello_r, hello_a, sep="**")
Bonjour Madame, 
 Monsieur.**Bonjour 'Madame, \n Monsieur.'**Bonjour 'Madame, \n Monsieur.'
st = "Bonjour, \n bonjour !"
print(st)
print("{!s}".format(st))
print("{!r}".format(st))
print("{!a}".format(st))
Bonjour, 
 bonjour !
Bonjour, 
 bonjour !
'Bonjour, \n bonjour !'
'Bonjour, \n bonjour !'

Souplesses de l’arg de .format().#

Avec .format(), les arguments à formater peuvent être indiqués par position implicite (par défaut comme jusqu’à présent) ou explicite mais aussi par nommage ou par liste/dictionnaire – dans la définition et dans l’appel pour les deux derniers.

La position des valeurs du conteneur arg argument de .format(arg) est précisée dans les { } de st_format :

  • de façon explicite avec {pos}

  • de façon nommée avec {nom}

  • en correspondance avec l’item i d’un argument lst avec {0[i]}

  • en correspondance avec la valeur de clé d’un un argument dict avec {0[clé]}

Ces positions peuvent être complétées d’une spécification de formatage.

st_pos =  "{1} {0} est {2}"
st_nom =  "{article} {sujet} est {complement}"
st_lst = "{0[0]} {0[1]} est {0[2]}"
st_dict = "{0[article]} {0[sujet]} est {0[complement]}"


print(st_pos.format("ciel", "le", "bleu"))
print(st_nom.format(article="la", sujet="mer", complement="calme"))
print(st_lst.format( ["la", "montagne", "violette"] ))
d = dict(complement="chaud", article="le", sujet="soleil") # syntaxe dictionnaire param. nommés
print(st_dict.format(d))
le ciel est bleu
la mer est calme
la montagne est violette
le soleil est chaud

Méthodes spécifiques (sans .format())#

On verra que certains traitements peuvent être obtenus avec des méthodes spécifiques aux str.

méthode

effet

str.center(nb)

centre strsur nbcaractères

str.rjust(nb)

justifie str à droite sur nb caractères

str.ljust(nb)

justifie str à gauche sur nb caractères

str.zfill(nb)

ajoute des zéros à gauche de str pour obtenir nb caractères

9.2. Synthèse#

9.2.1. Avoir les idées claires#

  • Connaitre les principes du formatage des données pour pouvoir retrouver rapidement dans la documentation (de cours ou de référence) les commandes pour effectuer ce traitement.

9.2.2. Savoir-faire#

  • Utiliser les formatages de base des types int et float de python

  • En s’appuyant sur les documents de cours ou de référence, définir et appliquer des formatages évolués et adaptés aux données manipulées avec python