Formati dati 1 - Introduzione

Scarica zip esercizi

Naviga file online

In questi tutorial parleremo di formati dei dati:

File testuali:

  • File a linee

  • CSV

  • breve panoramica sui cataloghi open data

  • menzione licenze (Creative Commons CC-Zero)

  • menzione JSON

Menzione file binari:

  • fogli Excel

Che fare

  • scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere:

formats
    formats1-lines.ipynb
    formats1-lines-sol.ipynb
    formats2.ipynb
    formats2-csv-sol.ipynb
    formats3-json.ipynb
    formats3-json-sol.ipynb
    formats4-chal.ipynb
    jupman.py

ATTENZIONE: Per essere visualizzato correttamente, il file del notebook DEVE essere nella cartella szippata.

  • apri il Jupyter Notebook da quella cartella. Due cose dovrebbero aprirsi, prima una console e poi un browser. Il browser dovrebbe mostrare una lista di file: naviga la lista e apri il notebook formats.ipynb

  • Prosegui leggendo il file degli esercizi, ogni tanto al suo interno troverai delle scritte ESERCIZIO, che ti chiederanno di scrivere dei comandi Python nelle celle successive.

Scorciatoie da tastiera:

  • Per eseguire il codice Python dentro una cella di Jupyter, premi Control+Invio

  • Per eseguire il codice Python dentro una cella di Jupyter E selezionare la cella seguente, premi Shift+Invio

  • Per eseguire il codice Python dentro una cella di Jupyter E creare una nuova cella subito dopo, premi Alt+Invio

  • Se per caso il Notebook sembra inchiodato, prova a selezionare Kernel -> Restart

File a linee

I file a linee tipicamente sono file di testo che contengono informazioni raggruppate per linee. Un esempio usando personaggi storici potrebbe essere un file così:

Leonardo
da Vinci
Sandro
Botticelli
Niccolò
Macchiavelli

Si nota subito una regolarità: le prime due linee contengono i dati di Leonardo da Vinci, prima il nome e poi il cognome. Le successive due linee hanno invece i dati di Sandro Botticelli, di nuovo prima il nome e poi il cognome, e così via

Un programma che potremo voler fare potrebbe essere leggere le linee e stampare a video nomi e cognomi così:

Leonardo da Vinci
Sandro Botticelli
Niccolò Macchiavelli

Per iniziare ad avere un’approssimazione del risultato finale, possiamo aprire il file, leggere solo la prima linea e stamparla:

[1]:
with open('people-simple.txt', encoding='utf-8') as f:
    linea=f.readline()
    print(linea)
Leonardo

Che è successo? Esaminiamo le varie linee:

il comando open

Il comando

open('people-simple.txt', encoding='utf-8')

ci permette di aprire il file di testo dicendo a Python il percorso del file 'people-simple.txt' e la codifica con cui è stato scritto (encoding='utf-8').

La codifica

La codifica dipende dal sistema operativo e dell’editor con cui è stato scritto il file. Quando apriamo un file, Python non può divinare la codifica, e se non gliela specifichiamo potrebbe aprirlo assumendo una codifica diversa dall’originale - tradotto, affidandoci al caso o sbagliando codifica in seguito potremmo vedere dei caratteri strani (tipo quadratini invece di lettere accentate).

In genere, quando apri un file, prova prima a specificare la codifica utf-8 che è la più comune scrivendo encoding='utf-8', e se per caso non va bene prova invece encoding='latin-1' (solitamente utile se il file è stato scritto su sistemi Windows). Se apri file scritti in posti più esotici, tipo in Cina, potresti dover usare un’altro encoding. Per approfondire queste questioni, quando hai tempo leggi Immersione in Python - Cap 4 - Stringhe e Immersione in Python - Cap 11 - File, entrambe letture caldamente consigliate.

il with

Il with definisce un blocco con all’interno le istruzioni:

with open('people-simple.txt', encoding='utf-8') as f:
    linea=f.readline()
    print(linea)

Abbiamo usato il with per dire a Python che in ogni caso, anche se accadono errori, vogliamo che dopo aver usato il file, e cioè eseguito le istruzioni nel blocco interno (il linea=f.readline() e print(linea)) Python deve chiudere automaticamente il file. Chiudere propriamente un file evita di sprecare risorse di memoria e creare errori paranormali. Se vuoi evitare di andare a caccia di file zombie mai chiusi, ricordati sempre di aprire i file nei blocchi with! Inoltre, alla fine della riga nella parte as f: abbiamo assegnato il file ad una variabile chiamata qui f, ma potevamo usare un qualunque altro nome.

ATTENZIONE: Per indentare il codice, usa SEMPRE sequenze di 4 spazi bianchi. Sequenze di 2 soli spazi per quanto consentite non sono raccomandate.

ATTENZIONE: A seconda dell’editor che usi, premendo TAB potresti ottenere una sequenza di spazi bianchi come accade in Jupyter (4 spazi che sono raccomandati), oppure un carattere speciale di tabulazione (da evitare)! Per quanto noiosa questa distinzione ti possa apparire, ricordatela perchè potrebbe generare errori molto difficili da scoprire.

ATTENZIONE: Nei comandi che creano blocchi come il with, ricordati di mettere sempre il carattere dei doppi punti : alla fine della linea !

Il comando

linea=f.readline()

mette nella variabile linea l’intera linea, come una stringa. Attenzione: la stringa conterrà alla fine anche il carattere speciale di ritorno a capo !

Ti chiederai da dove venga fuori quel readline. Come quasi tutto in Python, la nostra variabile f che rappresenta il file appena aperto è un oggetto, e ogni oggetto, a seconda del suo tipo, ha dei metodi particolari che possiamo usare su di esso. In questo caso il metodo è readline. Clicca qua per maggiori informazioni sugli oggetti.

Il comando seguente stampa il contenuto della stringa:

print(linea)

✪ 1.1 ESERCIZIO: Prova a riscrivere nella cella qua il blocco with appena visto, ed esegui la cella premendo Control-Invio. Riscrivi il codice con le dita, non con il copia e incolla ! Fai attenzione ad indentare correttamente con gli spazi il blocco.

Mostra soluzione
[2]:
# scrivi qui


Leonardo

✪ 1.2 ESERCIZIO: immagino ti starai chiedendo che cosa è esattamente quella f, e cosa faccia esattamente il metodo readline. Quando ti trovi in queste situazioni, puoi aiutarti con le funzioni type e help. Questa volta, copia e incolla direttamente sempre lo stesso codice qua sotto, ma aggiungi a mano dentro il blocco with i comandi:

  • print(type(f))

  • help(f.readline)      # Attenzione: ricordati il 'f.' prima del readline !!

  • help(f)

Ogni volta che aggiungi qualcosa, prova ad eseguire con Control+Invio e vedere cosa succede.

Mostra soluzione
[20]:
# scrivi qui il codice (copia e incolla)


Leonardo

type(f): <class '_io.TextIOWrapper'>

Help on built-in function readline:

readline(size=-1, /) method of _io.TextIOWrapper instance
    Read until newline or EOF.

    Returns an empty string if EOF is hit immediately.

Prima abbiamo messo il contenuto della prima linea nella variabile line, ora potremmo metterlo in una variabile dal nome più significativo, come nome. Non solo, possiamo anche direttamente leggere la linea successiva nella variabile cognome e poi stampare la concatenazione delle due:

[4]:
with open('people-simple.txt', encoding='utf-8') as f:
    nome=f.readline()
    cognome=f.readline()
    print(nome + ' ' + cognome)

Leonardo
 da Vinci

PROBLEMA ! La stampa mette comunque uno strano ritorno a capo. Come mai? Se ti ricordi, prima ho detto che readline legge il contenuto della linea in una stringa aggiungendo alla fine anche il carattere speciale di ritorno a capo. Per eliminarlo, puoi usare il comando rstrip():

[5]:
with open('people-simple.txt', encoding='utf-8') as f:
    nome=f.readline().rstrip()
    cognome=f.readline().rstrip()
    print(nome + ' ' + cognome)

Leonardo da Vinci

✪ 1.3 ESERCIZIO: Di nuovo, riscrivi il blocco qua sopra nella cella sotto, ed esegui la cella con Control+Invio. Domanda: che succede se usi strip() invece di rstrip()? Ed lstrip()? Riesci a dedurre il significato di r e l ? Se non ci riesci, prova ad usare il comando python help chiamando help(string.rstrip)

Mostra soluzione
[6]:
# scrivi qui


Leonardo da Vinci

Benissimo, abbiamo la prima linea ! Adesso possiamo leggere tutte le linee in sequenza. A tal fine possiamo usare un ciclo while:

[7]:
with open('people-simple.txt', encoding='utf-8') as f:
    linea=f.readline()
    while linea != "":
        nome = linea.rstrip()
        cognome=f.readline().rstrip()
        print(nome + ' ' + cognome)
        linea=f.readline()
Leonardo da Vinci
Sandro Botticelli
Niccolò Macchiavelli

NOTA: In Python ci sono metodi più concisi per leggere un file tdi testo linea per linea, ma abbiamo usato questo approccio per esplicitare tutti i passaggi

Cosa abbiamo fatto? Per prima cosa, abbiamo aggiunto un ciclo while in un nuovo blocco

Attenzione: nel nuovo blocco while, dato che è già all’interno del blocco esterno with, le istruzioni sono indentate di 8 spazi e non più 4! Se per caso sbagli gli spazi, possono succedere brutti guai!

Prima leggiamo una linea, e due casi sono possibili:

  1. siamo alla fine del file (o il file è vuoto): in questo caso la chiamata a readline() ritorna una stringa vuota

  2. non siamo alla fine del file: la prima linea è messa come una stringa dentro la variabile linea. Dato che Python internamente usa un puntatore per tenere traccia della posizione a cui si è durante la lettura del file, dopo una lettura questo puntatore è mosso all’inizio della riga successiva. In questo modo una chiamata successiva a readline() leggerà la linea dalla nuova posizione.

Nel blocco while diciamo a Python di continuare il ciclo fintanto che linea non è vuota. In questo caso, dentro il blocco while estraiamo il nome dalla linea e lo mettiamo nella variabile nome (rimuovendo il carattere extra di ritorno a capo con la rstrip() come fatto in precedenza), e poi procediamo leggendo la nuova riga ed estraendo il risultato dentro la variabile cognome. Infine, leggiamo di nuovo la linea dentro la variabile linea così sarà pronta per la prossima iterazione di estrazione nome. Se la linea è vuota il ciclo terminerà:

while linea != "":                   # entra il ciclo se la linea contiene caratteri
    nome = linea.rstrip()            # estrae il nome
    cognome=f.readline().rstrip()    # legge la nuova linea ed estrae il cognome
    print(nome + ' ' + cognome)
    linea=f.readline()               # legge la prossima linea

✪ 1.4 ESERCIZIO: Di nuovo come prima, riscrivi nella cella qua sotto il codice col while appena spiegato, facendo MOLTA attenzione all’indentazione (per la linea del with esterno fai pure copia e incolla):

Mostra soluzione
[8]:
# scrivi qui il codice col while interno


Leonardo da Vinci
Sandro Botticelli
Niccolò Macchiavelli

File a linee people-complex:

Guarda il file people-complex.txt, più complesso:

nome: Leonardo
cognome: da Vinci
data di nascita: 1452-04-15
nome: Sandro
cognome: Botticelli
data di nascita: 1445-03-01
nome: Niccolò
cognome: Macchiavelli
data di nascita: 1469-05-03

Supponendo di leggere il file per voler stampare questo output, come faresti ?

Leonardo da Vinci, 1452-04-15
Sandro Botticelli, 1445-03-01
Niccolò Macchiavelli, 1469-05-03

Suggerimento 1: Per ottenere dalla stringa 'abcde' la sottostringa 'cde', che inizia all’indice 2, puoi usare l’operatore di parentesi quadre, indicando l’indice di inizio seguito dai doppi punti :

[9]:
x = 'abcde'
x[2:]
[9]:
'cde'
[10]:
x[3:]
[10]:
'de'

Suggerimento 2: Per sapere la lunghezza di una stringa, usa la funzione len:

[11]:
len('abcde')
[11]:
5

✪ 1.5 ESERCIZIO: Scrivi qua sotto la soluzione dell’esercizio ‘People complex’:

Mostra soluzione
[12]:
# scrivi qui


Leonardo da Vinci, 1452-04-15
Sandro Botticelli, 1445-03-01
Niccolò Macchiavelli, 1469-05-03

Esercizio file a linee immersione-in-python-toc

Questo esercizio è più difficile, se sei alle prime armi puoi saltarlo e passare ai CSV.

Il libro Immersione in Python in Italiano è bello e ti fornisce un PDF, che però ha un problema: se provi a stamparlo scoprirai che manca l’indice. Senza perderci d’animo, abbiamo trovato un programmino che ci ha estratto i titoli in un file come segue, che però come scoprirai non è esattamente bello da vedere. Dato che siamo Python ninja, abbiamo deciso di trasformare i titoli grezzi in una tabella dei contenuti vera e propria. Sicuramente ci sono metodi più furbi per compiere questa operazione, come caricare il pdf in Python con una apposita libreria per i pdf, ma pareva un esercizio interessante.

Ti viene consegnato il file immersione-in-python-toc.txt:

BookmarkBegin
BookmarkTitle: Il vostro primo programma Python
BookmarkLevel: 1
BookmarkPageNumber: 38
BookmarkBegin
BookmarkTitle: Immersione!
BookmarkLevel: 2
BookmarkPageNumber: 38
BookmarkBegin
BookmarkTitle: Dichiarare funzioni
BookmarkLevel: 2
BookmarkPageNumber: 41
BookmarkBeginint
BookmarkTitle: Argomenti opzionali e con nome
BookmarkLevel: 3
BookmarkPageNumber: 42
BookmarkBegin
BookmarkTitle: Scrivere codice leggibile
BookmarkLevel: 2
BookmarkPageNumber: 44
BookmarkBegin
BookmarkTitle: Stringhe di documentazione
BookmarkLevel: 3
BookmarkPageNumber: 44
BookmarkBegin
BookmarkTitle: Il percorso di ricerca di import
BookmarkLevel: 2
BookmarkPageNumber: 46
BookmarkBegin
BookmarkTitle: Ogni cosa &#232; un oggetto
BookmarkLevel: 2
BookmarkPageNumber: 47

Scrivi un programma python per stampare e video il seguente output:

Il vostro primo programma Python  38
   Immersione!  38
   Dichiarare funzioni  41
      Argomenti opzionali e con nome  42
   Scrivere codice leggibile  44
      Stringhe di documentazione  44
   Il percorso di ricerca di import  46
   Ogni cosa è un oggetto  47

Per questo esercizio, dovrai inserire nell’output degli spazi artificiali, in una quantità determinata dalle righe BookmarkLevel.

DOMANDA: che cos’è lo strano valore &#232; alla fine del file originale ? Dobbiamo riportarlo nell’output ?

SUGGERIMENTO 1: Per convertire una stringa in numero intero, usa la funzione int:

[13]:
x = '5'
[14]:
x
[14]:
'5'
[15]:
int(x)
[15]:
5

Attenzione: int(x) ritorna un valore, e non modifica mai l’argomento x !

SUGGERIMENTO 2: Per sostituire un sottostringa in una stringa, si può usare la funzione replace:

[16]:
x = 'abcde'
x.replace('cd', 'HELLO' )
[16]:
'abHELLOe'

SUGGERIMENTO 4: Finchè c’è una sola sequenza da sostituire, va bene il replace, ma se avessimo un milione di sequenze orribili come &gt;, &#62;, &x3e;, che faremmo? Da bravi data cleaner, possiamo riconoscere che sono sequenze di escape HTML, perciò potremmo usare dei metodi specifici per queste sequenze come html.unescape. Provalo invece del replace e guarda se funziona!

NOTA: Prima di usare il metodo html.unescape, importa il modulo html con il comando:

import html

SUGGERIMENTO 3: Per scrivere n copie di un carattere, usa * come qua:

[17]:
"b" * 3
[17]:
'bbb'
[18]:
"b" * 7
[18]:
'bbbbbbb'

✪✪✪ 1.6 ESERCIZIO: Scrivi qua sotto la soluzione per file a linee immersione-in-python-toc, e prova ad eseguirla premendo Control + Invio:

Mostra soluzione
[19]:
# scrivi qui


   Il vostro primo programma Python  38
      Immersione!  38
      Dichiarare funzioni  41
         Argomenti opzionali e con nome  42
      Scrivere codice leggibile  44
         Stringhe di documentazione  44
      Il percorso di ricerca di import  46
      Ogni cosa è un oggetto  47

Prosegui

Continua con i file tabellari CSV