<jupyter_start><jupyter_text>Dictionaries, Set, Espressioni Regolari, Gestione delle eccezioni, File e Utilità di sistemaUn _dictionary_ è una struttura hash di coppie chiave-valore. Si ottiene attraverso la funzione built-in `dict()` e il letterale è racchiuso tra parentesi graffe `{ }`. Le chiavi hanno forma di stringhe e si utilizza la notazione array `['']` per ottenere il valore associato alla singola chiave. Un `dict` è un _iterable_.E' possibile ottenere un `dict` da un qualunque oggetto iterabile, oppure con la notazione `for ... in` ovvero specificando le chiavi ed i valori come _kwargs_ nella funzione `dict`<jupyter_code>phoneNumbers = dict([('anne', 4139), ('guido', 4127), ('jack', 4098)]) # ottiene un dictionary da una lista di tuple
print(phoneNumbers)
initials = {x : x.capitalize()[0] for x in ('mary','jack','dan')} # mappa gli elementi della tupla come chiavi ed i valori sono ottenuti dall'espressione dopo i ':'
print(initials)

ticTacToe = dict (tic=1,tac=2,toe=3)
print(ticTacToe)


topolino = {}

topolino['nome']='Topolino'
topolino['eta']=75
topolino['vive']='Topolinia'
topolino['famoso']=True
topolino['amici']={'Pippo','Pluto','Basettoni'} # questo è un set

print(topolino)

for k in topolino.keys(): # lista delle chiavi
    print(k,end=', ')
print()

for v in topolino.values(): # lista dei valori
    print(v,end=', ')
print()

for key, val in topolino.items(): # lista delle coppie chiave/valore come tuple
    print(key, val,sep=': ',end=', ')
print()


pluto=dict.fromkeys(topolino) # fromkeys crea un dict nuovo con le chiavi impostate a None
pluto['nome']='Pluto'
pluto['eta']=70
pluto['vive']=topolino.get('vive') # restituisce il valore corrispondente alla chiave passata come argomento
pluto['famoso']=True

if pluto['nome'] not in topolino['amici']: # in e not in sono operatori che danno un risultato booleano
    pluto['amici']={'nessuno'} # creo un set con un solo elemento
else:
    pluto['amici']={topolino['nome']} # creo un set con un elemento valutando una espressione

print(pluto)

friends=pluto.pop('amici') # elimina l'item e restituisce il valore

pluto.popitem()  # rimuove l'ultimo item dal dict

del pluto['eta'] # del cancella l'elemento su cui opera

print(friends,pluto)

pluto.clear() # cancella tutti gli item

print(pluto)

del pluto # cancella il nome pluto: da adesso in poi valutare pluto comporta un errore

pluto<jupyter_output>{'nome': 'Pluto', 'eta': 70, 'vive': 'Topolinia', 'famoso': True, 'amici': {'Topolino'}}
{'Topolino'} {'nome': 'Pluto', 'vive': 'Topolinia'}
{}<jupyter_text>SetUn set è un insieme di valori _non ripetuti_ racchiusi tra parentesi graffe `{ }` ***senza*** specifica di chiave. E' indicato per creare raggruppamenti di valori per cui sia rilevante giudicare l'appartenenza di un elemento all'insieme utilizzando `in` e `not in`.<jupyter_code>a = set('abracadabra')                      # uso della funzione built-in
b = {'a','l','a','c','a','z','a','m'}       # letterale di tipo set

print(a,b)                                  # stampa solo i valori unici

print(a - b)                              # complemento di a rispetto a b

print(a | b)                              # unione

print(a & b)                              # intersezione

print(a ^ b)                              # or esclusivo: a ∪ b - a ∩ b<jupyter_output>{'b', 'r', 'd', 'c', 'a'} {'z', 'c', 'm', 'a', 'l'}
{'d', 'r', 'b'}
{'b', 'r', 'z', 'd', 'c', 'm', 'a', 'l'}
{'c', 'a'}
{'d', 'm', 'b', 'l', 'r', 'z'}<jupyter_text>Gestione delle eccezioni PythonLe eccezioni si gestiscono con il costrutto:```pythontry:     codice da eseguireexcept :  blocco opzionale che intercetta l'eccezione calcolata con  e la gestisce     gestione della particolare eccezione intercettata Può esserci più di un blocco exceptelse:  blocco opzionale     codice eseguito se non è stata sollevata alcuna eccezionefinally:  blocco opzionale     codice eseguito in coda a tutti i gestori di eccezioni     a prescindere che siano state sollevate o meno```Lista delle eccezioni più comuni:	Python Built-in Exceptions						Exception			Cause of Error							AssertionError			Raised when assert statement fails.							AttributeError			Raised when attribute assignment or reference fails.							EOFError			Raised when the input() functions hits end-of-file condition.							FloatingPointError			Raised when a floating point operation fails.							GeneratorExit			Raise when a generator&39;s close() method is called.							ImportError			Raised when the imported module is not found.							IndexError			Raised when index of a sequence is out of range.							KeyError			Raised when a key is not found in a dictionary.							KeyboardInterrupt			Raised when the user hits interrupt key (Ctrl+c or delete).							MemoryError			Raised when an operation runs out of memory.							NameError			Raised when a variable is not found in local or global scope.							NotImplementedError			Raised by abstract methods.							OSError			Raised when system operation causes system related error.							OverflowError			Raised when result of an arithmetic operation is too large to be represented.							ReferenceError			Raised when a weak reference proxy is used to access a garbage collected referent.							RuntimeError			Raised when an error does not fall under any other category.							StopIteration			Raised by next() function to indicate that there is no further item to be returned by iterator.							SyntaxError			Raised by parser when syntax error is encountered.							IndentationError			Raised when there is incorrect indentation.							TabError			Raised when indentation consists of inconsistent tabs and spaces.							SystemError			Raised when interpreter detects internal error.							SystemExit			Raised by sys.exit() function.							TypeError			Raised when a function or operation is applied to an object of incorrect type.							UnboundLocalError			Raised when a reference is made to a local variable in a function or method, but no value has been bound to that variable.							UnicodeError			Raised when a Unicode-related encoding or decoding error occurs.							UnicodeEncodeError			Raised when a Unicode-related error occurs during encoding.							UnicodeDecodeError			Raised when a Unicode-related error occurs during decoding.							UnicodeTranslateError			Raised when a Unicode-related error occurs during translating.							ValueError			Raised when a function gets argument of correct type but improper value.							ZeroDivisionError			Raised when second operand of division or modulo operation is zero.<jupyter_code>a = iter(['pippo','pluto','paperino'])

while True:
    try:
        print(next(a))
    except StopIteration:
        print('Non ci sono più elementi!!')
        break

def dividi(num,den):
    quoziente = 0
    try:
        quoziente = num/den
    except ZeroDivisionError:
        print('Divisione per 0!!')
        return None
    except TypeError as te: # as consente di utilizzare l'oggetto eccezione nel blocco except
        if isinstance(num,type(0)) or isinstance(num,type(0.0)):
            print('Il denominatore non è un numero')
        elif isinstance(den,type(0)) or isinstance(den,type(0.0)):
            print('Il numeratore non è un numero')
        else:
            print('argomenti non numerici')
        print(f'\n\nEccezione: {type(te).__name__}\nMessaggio: {te.args[0]}')
        return None
    else:
        print(f'Il risultato è {quoziente}')
        return quoziente
    finally:
        # A solo titolo indicativo: qui potrebbero essere eseguite azioni esplicite di garbage collection per dati di grandi dimensioni
        del quoziente

dividi(3,4)<jupyter_output>Il risultato è 0.75<jupyter_text>Espressioni RegolariIl modulo `re` gestisce le espressioni regolari che hanno un letterale del tipo:```pythonr'[\w\.-]+@[\w\.-]+'```<jupyter_code>import re

str = 'purple <EMAIL> monkey dishwasher'
str1 = 'purple <EMAIL>, blah monkey <EMAIL> blah dishwasher'

match = re.search(r'[\w\.-]+@[\w\.-]+', str) # cerca l'espressione regolare

if match:
    print(match.group())       # stampa il gruppo di caratteri che fa parte del **primo** match
else:
    print('Nessuna corrispondenza')
    
match = re.search(r'([\w\.-]+)@([\w\.-]+)', str1) # cerca l'espressione regolare che è suddivisa in gruppi attraverso le parentesi tonde ( )

if match:
    print(match.group())       # stampa il gruppo di caratteri che corrisponde a tutto il primo match
    print(match.group(1))       # stampa il gruppo di caratteri che corrisponde al solo primo gruppo
    print(match.group(2))       # stampa il gruppo di caratteri che corrisponde al solo secondo gruppo
else:
    print('Nessuna corrispondenza')
    
tuples = re.findall(r'([\w\.-]+)@([\w\.-]+)', str1) # cerca tutte le occorrenze dell'espressione regolare

if tuples:

  print(tuples)  ## [('alice', 'google.com'), ('bob', 'abc.com')]
  for tuple in tuples:
    print(tuple[0],tuple[1],sep=': ')  ## username: host
else:
    print('Nessuna corrispondenza')<jupyter_output><EMAIL>
<EMAIL>
alice
google.com
[('alice', 'google.com'), ('bob', 'abc.com')]
alice: google.com
bob: abc.com<jupyter_text>FileI file sono oggetti che implementano un'interfaccia verso tre tipologie di flussi: testo, binari e bufferizzati. L'oggetto file si ottiene tramite la funzione `open()`:```pythonopen(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)```- `file`: è un _path-like_ object e corrisponde al percorso del file nel file system; la gestione del file system si ottiene dai moduli `os` e `os.path`- `mode`: la modalià di apertura del file    - `'r'` lettura (default)    - `'w'` scrittura: crea un nuovo file se non esiste e lo tronca se esiste già    - `'x'` solo creazione: se il file già esiste si genera un errore    - `'a'` append: scrive in coda senza troncare e crea un nuovo file se non esiste    - `'t'` text mode (default)    - `'b'` binary mode    - `'+'` aggiornamento: lettura/scritturaGli argomenti seguenti sono opzionali:- `buffering`: gestione del buffering- `encoding`: codifica; `encoding='utf-8'` per file Unicode; l'encoding di default è dipendente dalla piattaforma; Windows usa `'cp1252'` e Linux/UNIX `'utf-8'`- `errors`: specifica la codifica/decodifica defli errori- `newline`​: gestione del carattere di newline (valori disponibili: None, `' '`, `'\n'`, `'\r'`, and `'\r\n'`- `closefd`: dev'essere `True` altrimenti si genera un errore- `opener`: indica un gestore dell'apertura del file definito dall'utente che _deve_ restituire un descrittore di file aperto.`open()` restituisce un file object e l'eccezione `FileNotFoundError` in caso di file non trovato.```python Alcuni esempi di apertura di un filef = open("test.txt")       equivalente a 'r' o 'rt'f = open("test.txt",'w')   scrive il file in text modef = open("img.bmp",'r+b')  legge e scrive il file in binary mode Operazioni sui filef = open("test.txt",encoding = 'utf-8') esecuzione delle operazioni sul filef.close()  chiusura Gestione più sicura del file con garanzia di chiusura Uso di try ... finallytry:    f = open("test.txt",encoding = 'utf-8')     esegue le operazioni e intercetta le eccezionifinally:    f.close()  chiude il file sempre a prescindere dal fatto che ci siano state eccezioni``` Costrutto `with``with` genera un _runtime context manager_ a partire dalla valutazione di una espressione che fornisce il contesto di esecuzione e che può essere riferita all'interno del blocco tramite l'operatore `as`. I contesti with possono essere multipli. `with` esegue automaticamente i metodi `__enter__()` e `__exit__()` del contesto che quindi dev'essere un oggetto che implementa questi due metodi. Questo è ad esempio il caso dell'esecuzione di `open()`.```pythonwith open("test.txt",encoding = 'utf-8') as f:      esegue le operazioni e chiude automaticamente il file alla fine del blocco with```<jupyter_code>with open('./Python programming/hello.py',encoding='utf-8') as f:
    print(f.read(5))    # legge cinque elementi
    print(f.read(8))    # legge 8 elementi
    print(f.tell())     # riporta la posizione del cursore nel file
    f.seek(0)           # si riposiziona a 0
    
    # loop di lettura di tutte le linee            
    line = f.readline()
    while line != '':
        print(line)
        line = f.readline()
    
    f.seek(0) 
    
    # legge tutte le linee in una lista
    print(f.readlines())

# Creiamo un piccolo file csv (Comma Separated Values) da una lista di dict
persone = [{'matricola': 1234,'nome': '<NAME>', 'reparto': 'A'},
           {'matricola': 8976,'nome': '<NAME>', 'reparto': 'B'},
           {'matricola': 7732,'nome': '<NAME>', 'reparto': 'A'}]

with open('./Data/persone.csv','w',encoding='utf-8') as dataFile:
    
    # Dapprima scriviamo nel file la linea di intestazione
    # che è costituita dalle chiavi di uno qualunque dei dict
    for i,k in enumerate(persone[0].keys()):
        if i == len(persone[0].keys()) -1:
            dataFile.write(k+'\n')      # andiamo a capo dopo l'ultimo campo
        else:
            dataFile.write(k+', ')      # altrimenti mettiamo la virgola
    
    # Stampiamo per ogni riga, terminata dal carattere newline, gli elementi di ogni dict
    for i in range(len(persone)):
        dataFile.write(f'{persone[i]["matricola"]}, {persone[i]["nome"]}, {persone[i]["reparto"]}\n')<jupyter_output><empty_output><jupyter_text>Gestione dei file CSVPython fornisce un esplicito modulo `csv` per gestire la lettura e la scrittura di file csv che sono uno dei formati più diffusi per esportare dei dati da un database. Di seguito alcuni esempi di lettura.<jupyter_code>import csv

##
#
# csv.reader() legge un file csv come una lista di righe
# ciascuna delle quali è una lista di valori
#
with open('./Data/persone.csv', 'r') as csvFile:
    reader = csv.reader(csvFile)
    for row in reader:
        print(row)

##
#
# In caso di file csv con una sintassi particolare come linee vuote iniziali
# alcuni campi con le virgolette ovvero delimitatori diversi dalla virgola
# è possibile usare un 'dialetto' csv e registrarlo per leggere correttamente i dati
#
csv.register_dialect('myDialect',
                     delimiter = ';',       # nuovo delimitatore
                     quoting=csv.QUOTE_ALL, # tutti i campi vengono racchiusi da virgolette per omogeneità
                     skipinitialspace=True) # ci sono spazi dopo il delimitatore

with open('./Data/persone.csv', 'r') as csvFile:
    reader = csv.reader(csvFile, dialect='myDialect')
    
    for row in reader:
        print(row)

##
#
# In caso di file csv con una sintassi particolare come linee vuote iniziali
# alcuni campi con le virgolette ovvero delimitatori diversi dalla virgola
# è possibile usare un 'dialetto' csv e registrarlo per leggere correttamente i dati
#
csv.register_dialect('myDialect',
                     delimiter = ';',
                     quoting=csv.QUOTE_ALL,
                     skipinitialspace=True)

with open('./Data/persone.csv', 'r') as csvFile:
    reader = csv.DictReader(csvFile, dialect='myDialect')
    
    for row in reader:
        print(dict(row))
        
##
#
# aggiungiamo una riga da una lista di dati a persone.csv
#

row = [3344, 'ZZ Top', 'D']

with open('./Data/persone.csv', 'a') as csvFile:
    writer = csv.writer(csvFile)
    writer.writerow(row)

##
#
# Scriviamo un nuovo file a partire da una lista di liste, ognuna delle quali sarà una riga
# La prima lista conterrà i nomi dei campi
#

csvData = [['Quantità', 'Artista', 'Reparto'], ['21', 'Boy George', 'Pop'], ['56', 'Genesis', 'Rock'],['32', 'W.A. Mozart', 'Classica']]

csv.register_dialect('myDialect',
delimiter = ';',
quotechar = '"',                    # il dialetto utilizza anche un proprio carattere per quotare gli elementi
quoting=csv.QUOTE_ALL,
skipinitialspace=True)

with open('./Data/dischi.csv', 'w', encoding='utf-8') as csvFile:
    writer = csv.writer(csvFile, dialect='myDialect')
    writer.writerows(csvData)

print("writing completed")

##
#
# Analogo a prima, ma usiamo un DictWriter per scrivere i dati da dict
#

csvData = [{'Cognome e Nome': '<NAME>', 'Data di nascita': '03/08/1933', 'Luogo di nascita': 'Palermo', 'Provincia': 'PA', 'CF': 'XXXTTT33R44R675E'},
           {'Cognome e Nome': '<NAME>', 'Data di nascita': '12/05/1971', 'Luogo di nascita': 'Monza', 'Provincia': 'MI', 'CF': 'GGGVVV44U66M456P'},
           {'Cognome e Nome': '<NAME>', 'Data di nascita': '30/09/2000', 'Luogo di nascita': 'Macerata', 'Provincia': 'MC', 'CF': 'CCCBBB89R12O984F'}]


csv.register_dialect('myDialect',
delimiter = ';',
quotechar = '"',                    # il dialetto utilizza anche un proprio carattere per quotare gli elementi
quoting=csv.QUOTE_ALL,
skipinitialspace=True)

with open('./Data/anagrafica.csv', 'w') as csvfile:
    fieldnames = ['Cognome e Nome', 'Data di nascita', 'Luogo di nascita', 'Provincia', 'CF']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames, dialect="myDialect")
    writer.writeheader()
    writer.writerows(csvData)

print("writing completed")<jupyter_output>writing completed<jupyter_text>Gestione dei file `json`Il modulo `json` consente di leggere/scrivere informazioni da/a apposite strutture dati Python secondo la eguente tabella di conversione:						Python			JSON Equivalent									dict			object							list, tuple			array							str			string							int, float			number							True			true							False			false							None			null<jupyter_code>##
#
# Lettura di un file json e stampa normale e formattata
#

import json

with open('./Data/dischi.json',encoding='utf-8') as f:
    data = json.load(f)
    # Output: {'name': 'Bob', 'languages': ['English', 'Fench']}

print(data)

print(json.dumps(data, indent = 4, sort_keys=True))
##
# scrittura di dati organizzati in un dict su file json
#

person_dict = [{'Cognome e Nome': '<NAME>', 'Data di nascita': '03/08/1933', 'Luogo di nascita': 'Palermo', 'Provincia': 'PA', 'CF': 'XXXTTT33R44R675E'},
           {'Cognome e Nome': '<NAME>', 'Data di nascita': '12/05/1971', 'Luogo di nascita': 'Monza', 'Provincia': 'MI', 'CF': 'GGGVVV44U66M456P'},
           {'Cognome e Nome': '<NAME>', 'Data di nascita': '30/09/2000', 'Luogo di nascita': 'Macerata', 'Provincia': 'MC', 'CF': 'CCCBBB89R12O984F'}]

with open('./Data/persone.json', 'w', encoding='utf-8') as json_file:
  json.dump(person_dict, json_file)

print("writing completed")
##
# 
# File ed espressioni regolari
#

import re
import csv

searchFor = r"[1-9]+"

with open('./Data/persone.csv', 'r', encoding='utf-8') as f:
    strings=re.findall(searchFor,f.read())

strings<jupyter_output><empty_output><jupyter_text>Utilità di sistema File System -- `os, os.path, shutil`   - `filenames = os.listdir(dir)`: lista dei soli nomi dei file in `dir` esclusi `.` e `..`   - `os.path.join(dir, filename)`: crea un percorso da un nome di file e da un nome di cartella   - `os.path.abspath(path)`: restituisce la forma assoluta di un percorso   - `os.path.dirname(path), os.path.basename(path)` restituiscono rispettivamente il nome della cartella ed il nome del file da un percorso, ad esempio `dir/foo/bar.htm` restituisce rispettivamente `dir/foo` e `bar.html`   - `os.path.exists(path)`: verifica se il percorso esiste   - `os.mkdir(dir_path)`: crea una cartella alla fine del percorso   - `os.makedirs(dir_path)`: crea tutte le cartelle nel percorso   - `os.system(cmd)`: esegue il comando e stampa l'output nello standard output dello script chiamante ovvero della console, ritornando il codice di uscita; l'uscita ***non*** viene intercettata da alcuna struttura dati Python   - `shutil.copy(source-path, dest-path)`: copia dal percorso sorgente a quello destinazione   - `shutil.move(source-path, dest-path)`: sposta dal percorso sorgente a quello destinazione   - `shutil.rmtree(path)`: cancella ricorsivamente tutte le cartelle del percorso   - `shutil.make_archive(base_name, format, root_dir=None, base_dir=None)`: crea un archivio `base_name` nel formato specificato da `format` (`'zip'`, `'tar'`, ....) che verrà salvato in `root_dir`, mentre l'archiviazione parte da `base_dir`, entrambe di default la cartella corrente   - `shutil.unpack_archive(filename, extractdir=None, format=None)`: estrae un archivio `filename` nel specificato da formato `format` (`'zip'`, `'tar'`, ....) che verrà estratto in `extractdir`, di default la cartella corrente       Esecuzione dei comandi esterni -- `subprocess``subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)`: esegue il comando specificato nella lista `args` che contiene tutti i suoi argomenti, ad es. `ls -l .` corrisponde a `['ls', '-l', '.']`. Restituisce un oggetto `subprocess.CompletedProcess` i cui campi sono:- `args`: la lista degli argomenti del comando- `returncode`: il codice di ritorno- `stdout`: lista contenenete lo standard output (se `capture_output=True` ovvero `stdout=subprocess.PIPE` nella chiamata)- `stderr`: lista contenenete lo standard error (se `capture_output=True` ovvero `stderr=subprocess.PIPE` nella chiamata)Alcuni parametri rilevanti:- `input`: specifica una stringa di input che viene passata al comando; dev'essere una _byte string_ il cui letterale è della forma `b' .... '`, analogamente al formato di `stdout` e `stderr`- `cwd`: specifica la cartella in cui ci si deve portare per eseguire il comando- `timeout`: intervallo di tempo in secondi, trascorso il quale viene sollevata un'eccezione `TimeoutExpired` ed il processo termina- `shell=True`: esecuzione attraverso la shell- `check=True`: se il processo esce con un errore e viene sollevata un'eccezione `CalledProcessError` che nei suoi argomenti conserva codice, standard output e standard error- `universal_newlines=True`: gestisce i caratteri di new line e di spaziatura e genera una stringa normale e non una stringa di byteQualche esempio da eseguire nella console Python:<jupyter_code>##
#
# Cattura standard output e standard error (è come inserire capture_output=True)
#
import subprocess

subprocess.run(['ls', '-l', '.'],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
##
#
# Esecuzione attraverso la shell: l'output si modifica per effetto di questo perché
# è formattato secondo ciò che serve al processo di shell usato dall'utente
#
subprocess.run(['ls', '-l', '.'],stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)

##
#
# Uso diretto dell'interfaccia Popen che gestrisce esplicitamente i processi e crea le pipeline
# per ridirigere l'output su un file
#
from subprocess import Popen


path_to_output_file = './Data/myoutput.txt'

myoutput = open(path_to_output_file,'w+')

# Popen apre una pipeline ed usa gli stessi argomenti di subprocess.run()
p = Popen(["ls","-lha"], stdout=myoutput, stderr=subprocess.PIPE, universal_newlines=True)

output, errors = p.communicate() # restituisce una coppia di stringhe che contengono standard output ed error rispettivamente

output

# '' abbiamo rediretto lo standard output

errors

# '' non ci sono errori

# Leggiamo il file su cui abbiamo rediretto lo standard output

with open(path_to_output_file,"r") as f:
    print(f.read())
##
# redirezione di comandi in pipe tra loro con Popen
#
#

from subprocess import Popen,PIPE

# Ciò che segue è equivalente a ls -lha | grep "rw-r--r--"

# prima pipe che esegue 'ls -lha'
p1 = Popen(["ls","-lha"], stdout=PIPE,universal_newlines=True)

# secoinda pipe che esegue 'grep "rw-r--r--"' e ha come standar input lo standard output della precedente
p2 = Popen(["grep", "rw-r--r--"], stdin=p1.stdout, stdout=PIPE,universal_newlines=True)

p1.stdout.close() # chiudiamo il flusso di output della prima pipe

# raccogliamo l'output della seconda pipe e stampiamo
output = p2.communicate()[0]
print(output)<jupyter_output>-rw-r--r--@  1 pirrone  staff   6.0K Mar 10 19:57 .DS_Store
-rw-r--r--   1 pirrone  staff    14K Mar  2 09:46 Configurazione dell'ambiente Python.ipynb
-rw-r--r--   1 pirrone  staff   1.0K Jan 26 14:30 LICENSE
-rw-r--r--   1 pirrone  staff    35K Mar  3 10:26 Python programming 1.ipynb
-rw-r--r--   1 pirrone  staff    20K Mar  3 10:42 Python programming 2.ipynb
-rw-r--r--   1 pirrone  staff    61K Mar 10 20:12 Python programming 3.ipynb
-rw-r--r--   1 pirrone  staff    40K Oct 15 18:00 Python programming 4.ipynb
-rw-r--r--   1 pirrone  staff    21K Oct 19 15:27 Python programming 5.ipynb
-rw-r--r--   1 pirrone  staff   247B Jan 26 14:30 README.md<jupyter_text>HTTP -- package `urllib`- `urllib.request`: modulo che contiene i metodi per effettuare una richiesta    - `ufile = urllib.request.urlopen(url)`: metodo che apre una url e restituisce una `urllib.response`- `urllib.response`: modulo che fornisce una interfaccia file minimale con i metodi `read()`, `readline()`, e soprattutto con i metodi    - `urllib.reponse.geturl()`: restituisce la _base url_ della richiesta    - `urllib.reponse.info()`: restituisce un dict che contiene gli header inviati dal server e il resto della pagina    - `urllib.parse`: manipola le url secondo la RFC 1808 e successive    - `urllib.parse.urlencode(query)`: rappresenta `query`come una stringa ASCII che usa il carattere '%' per rappresentare i caratteri speciali non stampabili     - `urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)`: restituisce una _named tuple_ secondo il seguente schema:AttributeIndexValueValue if not presentscheme0URL scheme specifierscheme parameternetloc1Network location partempty stringpath2Hierarchical pathempty stringparams3Parameters for last pathelementempty stringquery4Query componentempty stringfragment5Fragment identifierempty stringusernameUser nameNonepasswordPasswordNonehostnameHost name (lower case)NoneportPort number as integer,if presentNone- `urllib.error`: modulo che esporta l'eccezione URLError e la sua sottoclasse HTTPError per la gestioen di errori HTTP<jupyter_code>##
#
# Scarica un file html da una data URL, visualizza le informazioni sulla risposta
# e la carica in un file temporaneo per poi stamparla; il file temporaneo viene poi cancellato
#

import shutil
import os
import tempfile
import urllib.request

with urllib.request.urlopen("http://www.unipa.it/persone/docenti/p/roberto.pirrone") as response:
    with tempfile.NamedTemporaryFile(delete=False) as tmp_file: # crea un file temporaneo con un nome 
                                                                # che non verrà cancellato
        print(response.geturl()) # stampa la base url
        print(response.info())   # stampa l'header della risposta HTTP
        shutil.copyfileobj(response, tmp_file) # copia l'oggetto response in tmp_file

print(tmp_file.name)      # tmp_file.name contiene il path assoluto del file temporaneo
with open(tmp_file.name) as html:
    for line in html.readlines():
        print(line)

os.unlink(tmp_file.name)   # cancella il file
##
#
# Parsing di una url e stampa delle sue componenti
#

res=urllib.parse.urlparse('http://user:pass@www.somedomain.pfx:8888/path/to/the/resource.html?req=val&req1=val1#anchor')

print(res)  # la tupla ParseResult mostra i campi fino all'indice 5 che corrispondono alle sei componenti base della
            # URL secondo la RFC, mentre i campi sucessivi si possono accedere solo tramite il nome e non con la 
            # notazione [...]

print(res.password)

print(res.port)
##
#
# Invia una richiesta POST
#

import urllib.parse
import urllib.request

url = 'https://www.w3schools.com/action_page.php'
values = {'firstname' : 'Roberto',
          'lastname' : 'Pirrone'}   # campi previsti dalla form che si trova all'indirizzo punttao da url

user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:69.0) Gecko/20100101 Firefox/69.0"
headers = {'User-Agent': user_agent}     # crea un semplice header della richiesta con lo user agent

data = urllib.parse.urlencode(values)    # encoding dei valori nel corpo della richiesta
data = data.encode('ascii')              # encoding finale dei dati come byte
req = urllib.request.Request(url, data, headers)  # creazione di un oggetto urllib.request.Request con 
                                                  # i dati che 
                                                  # genera una richiesta di tipo POST; viene aggiunto 
                                                  # anche lo header

with urllib.request.urlopen(req) as response: # incio dells richiesta e stampa della risposta
   for line in response.readlines():
    print(line)
##
#
# Invia una richiesta GET
#
import urllib.parse
import urllib.request

url = 'https://www.w3schools.com/action_page.php'
values = {'firstname' : 'Roberto',
          'lastname' : 'Pirrone'}   # campi previsti dalla form che si trova all'indirizzo punttao da url

user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:69.0) Gecko/20100101 Firefox/69.0"
headers = {'User-Agent': user_agent}     # crea un semplice header della richiesta con lo user agent

data = urllib.parse.urlencode(values)    # encoding dei valori nel corpo della richiesta

print(data)

full_url = url + '?' + data
 
req = urllib.request.Request(full_url, None, headers)  # creazione di un oggetto urllib.request.Request senza i dati  
                                                       # e genera una richiesta di tipo GET; viene aggiunto anche lo 
                                                       # header e i dati sono stati concatenati all'indirizzo

with urllib.request.urlopen(req) as response: # invio della richiesta e stampa della risposta
   for line in response.readlines():
    print(line)

##
#
# gestione degli errori
#

import urllib.parse
import urllib.request
from urllib.error import URLError, HTTPError

url = 'https://www.w3schools.com/action_page.php'
values = {'firstname' : 'Roberto',
          'lastname' : 'Pirrone'}   # campi previsti dalla form che si trova all'indirizzo punttao da url

user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:69.0) Gecko/20100101 Firefox/69.0"
headers = {'User-Agent': user_agent}     # crea un semplice header della richiesta con lo user agent

data = urllib.parse.urlencode(values)    # encoding dei valori nel corpo della richiesta


full_url = url + '?' + data
 
req = urllib.request.Request(full_url, None, headers)  # creazione di un oggetto
                                                       # urllib.request.Request senza i dati  
                                                       # e genera una richiesta di tipo GET; viene 
                                                       # aggiunto anche lo 
                                                       # header e i dati sono stati concatenati 
                                                       # all'indirizzo
try:
    response=urllib.request.urlopen(req)
except HTTPError as e:
    print('Il server non ha soddisfatto la richiesta!!')
    print('Codice errore: ', e.code)
except URLError as e:
    print('Connessione al server non riuscita!')
    print('Motivazione: ', e.reason)
else:
    for line in response.readlines():
        print(line)<jupyter_output>b'<!DOCTYPE html>\r\n'
b'<html>\r\n'
b'<meta charset="utf-8">\r\n'
b'<title>Forms action page</title>\r\n'
b'<link rel="stylesheet" href="/w3css/4/w3.css">\r\n'
b'<body class="w3-container">\r\n'
b'<h1>Submitted Form Data</h1>\r\n'
b'<h2>Your input was received as:</h2>\r\n'
b'<div class="w3-container w3-large w3-border" style="word-wrap:break-word">\r\n'
b'firstname=Roberto&lastname=Pirrone&nbsp;</div>\r\n'
b'\r\n'
b'<p>The server has processed your input and returned this answer.</p>\r\n'
b'\r\n'
b'<div class="w3-panel w3-pale-yellow w3-leftbar w3-border-yellow">\r\n'
b'<p><strong>Note:</strong> This tutorial will not teach you how servers are processing input.\r\n'
b'Processing input is explained in our <a href="/php/default.asp" target="_blank">PHP tutorial</a>.</p>\r\n'
b'</div>\r\n'
b'\r\n'
b'</body>\r\n'
b'</html>'
{'fraction_non_alphanumeric': 0.11174040928718944, 'fraction_numerical': 0.011608986795168658, 'mean_word_length': 3.629055619930475, 'pattern_counts': {'":': 0, '<': 69, '<?xml version=': 0, '>': 69, 'https://': 3, 'lorem ipsum': 0, 'www.': 5, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '554423', 'license': 'MIT', 'n_tokens_mistral': 11253, 'n_tokens_neox': 10697, 'n_words': 3478, 'path': 'Python programming 3.ipynb', 'repo_name': 'fredffsixty/Medical_Imaging', 'size': '32053'}