5: Input e Output

  • Come scrivere sullo schermo
  • Come controllare il modo con cui le informazioni sono scritte
  • Come leggere e scrivere su file

In questa sezione descriviamo come specificare il formato con cui stampare le informazioni sia sullo shermo che in un file.

5.1 Stampare sullo standard output (normalmente lo schermo)¶

La funzione print è il comando utilizzato più comunemente per stampare informazioni sullo “standard output device” che normalmente è lo schermo.

Ci sono due modi per usare print.

5.1.1 print semplice¶

Il modo più facile di usare il comando print è passargli l'elenco delle variabili da stampare separate da un virgola. Qualche esempio:

In [ ]:
a = 10
b = 'test text'
print(a)
In [ ]:
print(b)
In [ ]:
print(a, b)
In [ ]:
print("The answer is", a)
In [ ]:
print("The answer is", a, "and the string contains", b)

Python aggiunge uno spazio tra ogni coppia di oggetti che viene stampata.

Python va a capo dopo ogni chiamata a print. Per impedirlo, usate il parametro end= :

In [ ]:
# Comportamento di default
print("Printing in line one")
print("...still printing in line one (just kidding).")
In [ ]:
# sostituendo il simbolo di 'a capo' (\n) con uno spazio nel primo statement'
print("Printing in line one",end=" ")
print("...still printing in line one (now it works).")

5.1.2 Come controllare la rappresentazione delle variabili numeriche sotto forma di stringhe¶

Un sistema built-in di formattazione permette una grande flessibilità.

Le idee fondamentali attraverso esempi:

In [ ]:
"{} needs {} pints".format('Peter',4)     # inserire i valori nell'ordine in cui devono comparire
In [ ]:
"{0} needs {1} pints".format('Peter', 4)   # specificare l'indice dell'elemento
In [ ]:
"{1} needs {0} pints".format('Peter', 4)
In [ ]:
"{name} needs {number} pints".format(    # specificare il nome dell'elemento da
    name='Peter',number=4)               # stampare
In [ ]:
import math
"Pi is approximately {:f}.".format(math.pi)     # si può spcificare il format per i reali.
                                                # Notate che il format è introdotto da ":" 
                                                # all'interno della parentesi graffa

Una specificazione di formato del tipo W.Df significa che il numero reale deve essere stampato con una lunghezza totale di W caratteri e D cifre dopo il punto decimale.

In [ ]:
"Pi is approximately {:.2f}.".format(math.pi)   # si può specificare il numero di cifre dopo la virgola
In [ ]:
"Pi is approximately {:6.2f}.".format(math.pi)  # e la lunghezza totale

Un esempio di come mescolare formati e ordine delle variabili:

In [ ]:
"{1:10.8f} --- {0:7.3e} pints".format(3*math.pi, math.pi)

5.1.3 f-strings: il metodo più semplice e recente di specificare il format¶

È sufficiente mettere il simbolo f, da cui il nome f-strings, di fronte al delimitatore iniziale della stringa e poi, all'interno della stringa stessa specificare variabile e formato fra parentesi graffe.

In [ ]:
my_a = math.pi
print(f"a = {my_a:7.4f}")
In [ ]:
print(f"2*Pi is approximately {2*math.pi:4.2f}.")

Comandi di formattazione¶

Una lista dei formati comunemente usati usando l'unità astronomica (distanza media Sole-Terra in metri): AU = 149597870700 m.

specifier style Example output for AU
f floating point 149597870700.000000
e exponential notation 1.495979e+11
g shorter of %e or %f 1.49598e+11
d integer 149597870700
x exadecimal 22d4ba5a6c
o octal 2132456455154
s str() 149597870700
In [ ]:
AU = 149597870700  # unità astronomica [m]
AU_f = f"{AU:f}"        # la prima linee della tavola
AU_f
In [ ]:
AU_f1 = f"{AU:.1f}"        # la prima linee della tavola con una sola cifra dopo il punto
AU_f1
In [ ]:
AU_e = f"{AU:e}"       # la seconda linee della tavola. Il formato esponenziale ha una cifra prima del punto.
AU_e
In [ ]:
AU_e4 = f"{AU:.4e}"       # la seconda linee della tavola con quattro cifre dopo il punto
AU_e4

Tabulare dati con le f-strings¶

Il simbolo >, <, ^ allinea le variabili a destra, sinistra, centro dello spazio disponibile. L'allineamento a destra è il default per le variabili numeriche; l'allineamento a sinistra è il default per quasi tutte gli altri tipi di variabili.

In [8]:
Table = [[1,2,3],[5,6,7],[8,9,10]]
info = ["dato 1","dato 2","dato 3"]
print(f"{info[0]:>8s} {info[1]:>8s} {info[2]:>8s}")
print(30*'-')
for i in range(len(Table)):
    print(f"{Table[i][0]:8d} {Table[i][1]:8d} {Table[i][2]:8d}") 
#    print(f"{Table[i][0]:i8} {Table[i][1]:i8} {Table[i][2]:i8}") 
  dato 1   dato 2   dato 3
------------------------------
       1        2        3
       5        6        7
       8        9       10

Separando più chiaramente le colonne

In [9]:
Table = [[1,2,3],[5,6,7],[8,9,10]]
info = ["dato 1","dato 2","dato 3"]
print(34*'-')
print(f"| {info[0]:>8s} | {info[1]:>8s} | {info[2]:>8s} |")
print(34*'-')
for i in range(len(Table)):
    print(f"| {Table[i][0]:8d} | {Table[i][1]:8d} | {Table[i][2]:8d} |") 
print(34*'-')
----------------------------------
|   dato 1 |   dato 2 |   dato 3 |
----------------------------------
|        1 |        2 |        3 |
|        5 |        6 |        7 |
|        8 |        9 |       10 |
----------------------------------

Effetto di allineamenti diversi:

In [11]:
Table = [[1,2,3],[5,6,7],[8,9,10]]
info = ["dato 1","dato 2","dato 3"]
print(34*'-')
print(f"| {info[0]:8s} | {info[1]:^8s} | {info[2]:>8s} |")
print(34*'-')
for i in range(len(Table)):
    print(f"| {Table[i][0]:^8d} | {Table[i][1]:<8d} | {Table[i][2]:8d} |") 
print(34*'-')
#    print(f"{Table[i][0]:i8} {Table[i][1]:i8} {Table[i][2]:i8}") 
----------------------------------
| dato 1   |  dato 2  |   dato 3 |
----------------------------------
|    1     | 2        |        3 |
|    5     | 6        |        7 |
|    8     | 9        |       10 |
----------------------------------

Come incolonnare numeri reali e interi richiedendo lo stesso numero di cifre dopo il punto di separazione:

In [17]:
Table = [[1.2,2,3.14],[-5.0,6.17,7],[8,9,10]]
info = ["dato 1","dato 2","dato3"]
print(f"{info[0]:>12s} {info[1]:>12s} {info[1]:>12s}")
print(42*'-')
for i in range(len(Table)):
    print(f"{Table[i][0]:12.2f} {Table[i][1]:12.2f} {Table[i][2]:12.2f}") 
#    print(f"{Table[i][0]:i8} {Table[i][1]:i8} {Table[i][2]:i8}") 
      dato 1       dato 2       dato 2
------------------------------------------
        1.20         2.00         3.14
       -5.00         6.17         7.00
        8.00         9.00        10.00
Ulteriori informazioni¶
  • Esempi http://docs.python.org/library/string.html#format-examples

  • Python Enhancement Proposal 3101

  • Python library String Formatting Operations

  • Old string formatting

  • Introduction to Fancier Output Formatting, Python tutorial, section 7.1

  • pyformat.info

5.2 Leggere e scrivere files¶

Ecco un programmma che

  1. crea un file di nome test.txt,

  2. scrive del testo nel file,

  3. chiude il file.

I dati che vengono immagazzinati nel file test.txt sono:

Writing text to file. This is the first line.
And the second line.
Third line!!!!!!!
In [ ]:
# 1. Scrivere in un file
out_file = open("test.txt", "w")          # Il file viene aperto/creato in scrittura.
                                          # 'w' vuol dire write.
out_file.write("Writing text to file. This is the first line.\n"+\
               "And the second line.\n Third line!!!!!!!")
# Il singolo carattere "\n" segnala la fine di una riga. Vuol dire "a capo".
out_file.close()                          # chiude il file

La cella seguente

  1. apre il file di nome test.txt,

  2. legge il testo dal file,

  3. stampa il testo sullo schermo.

  4. chiude il file

In [ ]:
 
# 2. Leggere dal file
in_file = open("test.txt", "r")           # Il file viene aperto in lettura. 'r' vuol dire read.
text = in_file.read()                     # Legge tutto il file in una variabile "text" di 
                                          # tipo stringa
in_file.close()                           # chiude il file
In [ ]:
# 3. Mostrare i dati
print(text)

Più in dettaglio, il file viene aperto con il comando open. L'oggetto file aperto viene assegnato alla variabile out_file. Il testo viene scritto nel file usando il metodo out_file.write. Si noti che nell'esempio più sopra, al metodo write è stata passata una stringa. Si possono usare, ovviamente, tutte specificazioni di formato discusse in precedenza — si veda formatted printing e new style formatting. È buona pratica usare close() su tutti i files in cui si è finito di leggere e scrivere. Se un programma Python finisce in modo controllato (cioè non per una caduta di tensione o un improbabile bug del linguaggio o del sistema operativo) tutti i files aperti vengono chiusi non appena i file objects vengono distrutti. Tuttavia, chiuderli esplicitamente non appena possibile è uno stile migliore di programmazione.

Metodi ed esempi di lettura e scrittura su file¶

Creiamo un file chiamato myfile.txt che contiene le tre linee di testo seguenti:

This is the first line.
This is the second line.
This is a third and last line.

Il metodo write non aggiunge il carattere newline (\n) alla fine di ogni operazione di scrittura

In [ ]:
f = open('myfile.txt', 'w')
f.write('This is the first line.\n'
        'This is the second line.\n'
        'This is the third and last line.')
f.close()

Modi equivalenti:

In [ ]:
f1 = open('myfile1.txt', 'w')
f1.write('This is the first line.\n''This is the second line.\n''This is the third and last line.')
f1.close()
In [ ]:
f2 = open('myfile2.txt', 'w')
f2.write('This is the first line.\n'+'This is the second line.\n'+'This is the third and last line.')
f2.close()

È sbagliato passare a write più stringhe separate da virgole. write accetta un solo argomento.

In [ ]:
f3 = open('myfile3.txt', 'w')
f3.write('This is the first line.\n','This is the second line.\n','This is the third and last line.')
f3.close()

fileobject.read()¶

Il metodo fileobject.read() legge tutto il file, e lo restituisce come una singola stringa (inclusi i caratteri di "a capo" \n).

In [ ]:
f = open('myfile.txt', 'r')
f.read()
In [ ]:
f.close()

fileobject.readlines()¶

Il metodo fileobject.readlines() restituisce una lista di stringhe, in cui ciascun elemento della lista corrisponde a una linea del file:

In [ ]:
f = open('myfile.txt', 'r')
f.readlines()
In [ ]:
f.close()

Questo metodo viene spesso utilizzato per iterare sulle linee, compiendo delle operzioni su ciascuna linea. Per esempio:

In [ ]:
f = open('myfile.txt', 'r')
for line in f.readlines():
    print(f"{len(line)} characters")
f.close()

Si noti che readlines() immagazzina tutto il file in una lista di stringhe. Non è un problema se si è sicuri che il file è piccolo e che può essere contenuto nella memoria disponibile.

In questo caso, possiamo chiudere il file prima di processarne il contenuto:

In [ ]:
f = open('myfile.txt', 'r')
lines = f.readlines()
f.close()
for line in lines:
    print("%d characters  %s" % (len(line),line))
In [ ]:
lines

Come iterare sulle linee (file object)¶

Esiste una notazione ancora più semplice per leggere un file linea per linea che (1) legge solo una linea alla volta (e quindi è adatto anche a files grandi) e (2) produce un codice più compatto:

In [ ]:
f = open('myfile.txt', 'r')
for line in f:
    print(f"{len(line)} characters")
f.close()

In questo caso, il "file handle" f agisce come un iteratore e restituisce la linea seguente a ogni iterazione del for-loop fino alla fine del file (quando il for-loop finisce). In alternativa si può usare il metodo readline che restituisce una riga alla volta:

In [ ]:
f = open('myfile.txt', 'r')
l1 = f.readline()
print(l1)
l2 = f.readline()
print(l2)
f.close()

Nozioni più avanzate: il context manager with¶

La documentazione di Python consiglia accedere ai file con la keyword with:

In [ ]:
with open('myfile.txt') as f:
    for line in f:
        print(f"{len(line)} characters")

Questa notazione chiude automaticamente il file alla fine delle operazioni contenute nel blocco with anche se il programma si fermasse per un errore. Il comando close non è più necessario.

Lettura/scrittura su file in directory diversa da quella di lavoro¶

La directory di lavoro si trova con il comando (magico)

In [ ]:
%pwd

Aprire un file già esistente utilizzando il path assoluto

In [ ]:
with open(r"/Users/maina/cernbox/python/MyCourse/path_test_dir/pippo1.txt") as filein:
    for line in filein:
        print(f"{line} :: {len(line)} characters")

Creare un nuovo file utilizzando il path assoluto e passando il parametro "w" al comando open

In [6]:
lines = ["pippo", "pluto", "non c'è trippa per gatti"]
with open(r"/Users/maina/cernbox/python/MyCourse/path_test_dir/pippo2.txt","w") as fileout:
    for line in lines:
        fileout.write(line+"\n")

Check:

In [ ]:
test = open(r"/Users/maina/cernbox/python/MyCourse/path_test_dir/pippo2.txt")
res = test.read()
print(res)
res

Aprire un file già esistente utilizzando il path relativo

In [ ]:
with open(r"../path_test_dir/pippo1.txt") as filein:
    for line in filein:
        print(f"{line} :: {len(line)} characters")

Notate come nelle celle precedenti il path venga passato in stringhe che hanno la lettera r prima del delimitatore. Questo tipi di stringhe si chiamano raw strings. Tutto il testo contenuto nella stringa viene scritto esattamente come appare, per esempio "\n" viene interpretato come backslash + n e non come il simbolo di a capo.

Nozioni più avanzate: zip¶

Partendo da due o più oggetti iterabili (stringhe, liste, ntuple) di uguale lunghezza restituisce un iteratore che combina il contenuto degli oggetti di partenza.
Esempi:

In [ ]:
l1 = [1,2,3]
l2 = ['a','b','c']
list(zip(l1,l2))
In [ ]:
l1 = 'pippo'
l2 = 'pluto'
list(zip(l1,l2))
In [ ]:
l1 = [1,2,3,4,5]
l2 = 'pluto'
list(zip(l1,l2))

Imparare Facendo

  1. Aprite in lettura il file "../Data/Iris_Dataset.csv" assegnandolo alla variabile filein.
    1. Importate il contenuto del file nella variabile filein usando il metodo read.
    2. Chiudete il file.
    3. Separate le linee con split usando il carattere "\n" (newline) come separatore.
    4. Saltate la prima riga e stampate le cinque righe seguenti sullo schermo.
  2. Aprite in lettura il file "../Data/Iris_Dataset.csv" assegnandolo alla variabile filein.
    1. Importate il contenuto del file nella lista fileList usando il metodo readlines.
    2. Chiudete il file.
    3. Estraete il secondo valore da ciascuna riga, la prima esclusa. Stampate il valore numerico sullo schermo.
Informazioni ulteriori¶

Input and output, Tutorial, Section 7.2