Download Python - Dipartimento di Informatica

Document related concepts
no text concepts found
Transcript
Python: Introduzione al
linguaggio ed esercizi
Marco Di Felice
Sistemi Operativi, AA 2010-2011
Dipartimento di Scienze dell’Informazione
Universita’ degli Studi di Bologna
… Da dove iniziare
 Qualche testo consigliato (e reperibile ON-LINE) per iniziare
a programmare in Python:
How to think like a Computer Scientist. Learning with
Python – A.Downey, J. Elkner, C. Meyers (GNU)
Dave into Python – Mark Pilgrim-
Il linguaggio Pyhton
 Ideato negli anni ‘80 da G. van Rossum
 Versione attuale del linguaggio: 2.6
 Prevalentemente object-oriented, ma multi-paradigma
(object-oriented, procedurale, funzionale, etc)
 Utilizza un interprete per l’esecuzione (non compilato)
 Dispone di librerie molto vaste per: parsing (HTML/XML),
networking, GUI, accesso a database, Web scripting, etc
Eseguire programmi Pyhton
 Due possibili modalita’ di esecuzione:
1. Modalita’ interattiva
$$ python
>> a=3+5
1. Modalita’ con Program Files
$$ vim myprogram.py
$$ python myprogram.py
Variabili, Tipi, Espressioni
 In un programma Python non e’ necessario dichiarare le
variabili ed il loro tipo.
 Il tipaggio avviene dinamicamente a run-time.
 Assegnamento di valori a a variabili.
message=“Hello world”
a=5
x=2.34
>>type(message)
<type ‘str’>
Espressioni
 Operatori matematici: + - / * // ** %
 Operatori logici: and or not
 Operatori di confronto: >, <, >=, <=
 Assegnamento: =
 Costanti Booleane: True False
 Python <versione 2.2.1  Non esiste il tipo di dato
booleano. FALSO: 0, stringa vuota “ “, lista vuota [],
dizionario vuoto {}
Costrutti di selezione
 Costrutti di selezione: if-else / if-elif- … - else
IF CONDIZIONE:
SEQUENZA DI COMANDI RAMO IF
ELSE
SEQUENZA DI COMANDI RAMO ELSE
if x==y:
print x, “ and “,y,” are equal “
else
print x, “ and “,y,” are different “
Costrutti di iterazione
 Costrutti di iterazione: while
WHILE CONDIZIONE:
SEQUENZA DI COMANDI DEL CICLO
X=1.0
while x<10.0:
print x,” “,math.log(x)
x=x + 1.0
Indentazione e Blocchi
 Python utilizza l’indentazione (e non le parentesi
graffe) per distinguere l’inizio e la fine di un blocco (es.
Il codice da eseguire all’interno di un ciclo).
 Per questo motivo, indentare bene il codice e’
fondamentale!
while n>0:
while n>0:
n=n-1
n=n-1
print n
print n
DIVERSO!!
Dichiarazione di Funzioni
 Keyword def per identificare l’inizio di una funzione
DEF nomeFUNZIONE (argomenti):
CORPO della FUNZIONE
RETURN valore (opzionale)
 Per richiamare una funzione:
nomeFUNZIONE (argomenti)
Funzioni Lambda
 Python consente di definire al volo piccole funzioni in
una sola riga (lambda-funzioni).
>> g= lamdba x: x**2
>> g(4)
>> 16
• Le funzioni lambda non possono contenere comandi e
non possono contenere piu’ di un’espressione
Dichiarazione di Funzioni
 (ES1): Scrivere il codice della funzione fattoriale:
Dichiarazione di Funzioni
 (ES1): Scrivere il codice della funzione fattoriale:
# Factorial function
def factorial(n):
if (n==0):
return 1
else
return n*factorial(n-1)
>> print factorial(4)
>> 24
Parametri e Funzioni
 Python consente di definire funzioni con parametri
opzionali; se la funzione e’ chiamata senza
argomento, l’argomento prende il valore predefinito
(indicato nella signature della funzione).
def power(a,b=2):
return a**b
>> power(4,3)
>> power(4)
Operazioni su Stringhe
 In Python, una stringa e’ una lista di caratteri.
message=“Hello world”
 La funzione len restituisce la lunghezza
>> len(message)
>> 11
 L’operatore [] consente di accedere ai singoli caratteri che
compongono la stringa:
>> print message[0]
>> ‘H’
Operazioni su Stringhe
>> message=“Hello world”
>> print message [0]
>> ‘H’
>> print message [2:3]
>> ‘l’
(Seleziona una sottostringa)
>> print message [2:]
>> ‘llo World’
(Seleziona una sottostringa)
>> print message [-1]
>> ‘d’
Operazioni su Stringhe
 Le stringhe sono liste IMMUTABILI.
message[0]=‘G’
NON SI PUO’ FARE!!
 Libreria di funzioni su stringhe
import string
Liste predefinite della classe string:
string.lowercase
string.uppercase
String.digits
Operazioni su Stringhe
 L’operatore for … in consente di ciclare su tutti gli
elementi di una lista
for c in str:
print c
 L’operatore in verifica la presenza di un carattere in
una stringa.
if c in str:
print “Found!”
Operazioni su Stringhe
 (ES2): Scrivere una funzione check_string(str)
che riceve in input una stringa, e ritorna 0 se la stringa
str e ben formata, 1 altrimenti.
 Assumiamo che una stringa sia ben formata se
contiene solo caratteri minuscoli.
Operazioni su Stringhe
import string
def check_string(str):
for c in str:
if not(c in string.lowercase):
return 0
return 1
>> print check_string(“hello), “ “, check_string(“Hello”)
>> 1 0
Liste di Elementi
 In Python, una lista e’ un insieme ordinato di valori, in
cui ciascun valore e’ identificato da un indice.
[]
LISTA VUOTA
[1,2,3,4,5]
[“Hello”, “World”, “Python”]
 Gli elementi possono essere eterogenei:
[“Hello”,1,3.4,5]
[“Hello”, [1,2], 4, 10, [1,2,3]]
Liste di Elementi
Come con le stringhe:
 [] per accedere ad un elemento della lista
 in verifica la presenza di un elemento in una lista
 len restituisce la lunghezza della lista
 + concatena due liste
 * ripete una lista un dato numero di volte
Liste di Elementi
A differenza delle stringhe, le liste sono MUTABILI
a=[1,2,3,4], a[0]=-1
 del per rimuovere un elemento della lista
del a[0]
 append aggiunge un elemento alla lista (in fondo)
 insert aggiunge un elemento in una posizione specifica
a.append(6)
a.insert(0,6)
Liste di Elementi
 Le liste sono passate per riferimento e non per valore.
a=[1,2,3]
b=a
a
a
b
b
[1,2,3]
[1,2,3]
[1,2,3]
• … E se invece b=a[:] ??
Liste di Elementi
 (ES3) Data la lista seguente:
a=[[1,2],3,4,5,6]
Definire quali delle operazioni sono valide e quali no.
 a[0][0]=5
 print a[0][-3]
 print a[0][-1]
 a[5]=‘b’
 a[2:4]=[2]
Liste di Elementi
 (ES4) Determinare l’output del programma seguente:
a=[‘a’,’b’,[‘b’,’c’],1,2,3]
del a[0]
a[1][0]=‘a’
c=a[2:4]
d=a[1]
e=c+d
print e
Liste di Elementi
 (ES5) Determinare l’output del programma seguente:
def fun(a):
return a[2:]
a=[1,2,3,4,5]
b=a
b[3]=6
c=fun(a)
c[2]=3
print c
Liste di Elementi
 (ES6) Scrivere un programma che legge input 5
numeri interi da tastiera. Ogni numero letto viene
inserito in una lista solo se non e’ un duplicato di
un numero gia’ letto. Se e’ un duplicato, il
programma continua la lettura da tastiera finche’
un numero non duplicato viene digitato. Dopo aver
letto i 5 valori, il programma ne calcola la media e
la stampa a video.
Liste di Elementi
# Read an integer value from the keybord
def read_number():
message="Please insert an integer value "
read=input(message)
return read
# Returns a list of 5 non-replicated values
def read_list_values():
listread=[]
# Number of readings from the input
numread=0
while (numread <5):
val=read_number()
# Check if the reading is valid
if not (val in listread):
listread.append(val)
numread+=1
else:
print "This is a duplicated value ..."
return listread
Liste di Elementi
# Main program
listv=read_list_values()
# Initialize the average value
average=0.0
# Compute the average value
for val in listv:
average+=val
average=average / len(listv)
print " The average value is ...", average
Liste di Elementi
 List comprehension => Tecnica compatta per
mappare una lista in un’altra applicando una funzione a
ciascuno degli elementi della lista.
>> li=[1,2,3,4,5]
>> li2=[elem * 4 for elem in li]
>> print li2
>> [4,8,12,16,20]
Liste di Elementi
 List comprehension + Filtri => E’ possibile
aggiungere dei filtri, in modo che alcuni elementi
vengano mappati ed altri restino alterati.
>> li=[1,2,3,4,5]
>> li2=[elem * 4 for elem in li if elem >2 ]
>> print li2
>> [12,16,20]
Liste di Elementi
 (ES7) Scrivere una funzione
check_sum_present(li, value) che prende in
input una lista di interi (si assume senza elementi
duplicati) ed un valore e verifica se nella lista ci sono
due elementi a,b tali che a+b=value. La funzione
deve restituire la lista di tutte le coppie [a,b] che
soddisfano la condizione.
Liste di Elementi
def check_sum_present(li, value):
return [ [elem,value-elem] for elem
in li if (((value-elem) in li) and (valueelem !=elem )) ]
li=[1,2,3,4,5,6,7,8]
print check_sum_present(li,11)
Tupla di Elementi
 Una tupla di elementi e’ simile ad una lista, ma a
differenza delle liste e’ IMMUTABILE.
tuple=1,2,3,4,5
tuple=(‘a’,’b’,’c’,’d’,’e’)
 Le tuple sono utili per fare swap di variabili o
assegnamenti multipli:
y, x = x, y
a, b, c, d = 1, ‘Hello’, 4, 5.6
Tupla di Elementi
A che servono le tuple?
 Le tuple sono piu’ veloci delle liste =>
utilizzare le tuple nel
caso in cui si debba solo iterare su un insieme di valori e non si
debba modificarli.
 Consentono di proteggere dalla scrittura i dati che non
devono essere modificati.
 Le tuple, a differenza delle liste, possono essere usate
come chiavi di un dizionario.
Dizionari
 Un dizionario e’ un insieme di coppie: <chiave,
valore>, in cui la chiave non deve essere
necessariamente un intero (a differenza delle liste).
dict={}
dict[‘Mario’]=“0861343242”
dict[‘Monica’]=“086243434”
dict{‘Mario’:’0861343242’, ‘Monica’: …}
Dizionari
 Il metodo len restituisce il numero di elementi
 Il metodo keys resistuisce la lista delle chiavi
 Il metodo values restituisce la lista dei valori
 Il metodo del elimina un elemento dalla lista
 Il metodo clear cancella tutto il contenuto di un dizionario
>> print dict.keys()
>> print dict.values()
>> del dict[2]
Dizionari
 Il metodo get restituisce il valore associato ad una certa
chiave:
>> print dict.get(“Mario”)
>> print dict.get(“Mario”,”Nome non trovato”)
• Il metodo has_key ritorna 1 se la chiave appare nel
dizionario, 0 altrimenti.
>> print dict.has_key(“Mario”)
>> True
Dizionari
 Non possono esserci duplicazioni di chiavi in un
dizionario.
 Gli elementi di un dizionario NON sono ordinati.
 Valori e chiavi possono assumere qualsiasi tipo. Non
necessariamente tutte le chiavi devono avere lo stesso
tipo.
dict={“0”:120,”Marco”:32,”1.0”:[1,2,3]}
Dizionari
 (ES8) Scrivere un programma che calcola il prodotto di
due matrici (supponiamo entrambe le matrici abbiano
dimensione NxN)
 (ES9) Ottimizzare il programma precedente nel caso in
cui le matrici siano sparse (cioe’ gran parte dei valori
delle matrici siano settati a 0)
Dizionari
 (ES10) Indicare l’output del programma seguente.
str=“hello”
dict={‘h’:1,’e’:2,’l’:3}
val=0
for c in str:
val=val+dict.get(c,-1)
print val
Dizionari
 (ES11) Indicare l’output del programma seguente.
def fun(d,x):
if d.has_key(x):
d[x]=3
dic={‘a’:1,’b’:2,’c’:4}
dic2=dic.copy()
dic3=dic
del dic[‘a’]
fun(dic2,’a’)
fun(dic3,’a’)
dic2[‘b’]=dic2[‘a’]+dic3.get(‘a’,-2)
print dic2[‘b’]
Classi ed Oggetti
 Python e’ un linguaggio ad oggetti; l’astrazione di
classi ed oggetto ha molti punti in comune con altri
linguaggi di programmazione (es. Java)
class Point:
def __init__(self,x=0,y=0):
self.x=x
self.y=y
Classi ed Oggetti
 Il metodo __init__ e’ Il costruttore della classe.
 self e’ il riferimento all’oggetto corrente, tramite il quale si puo’
accedere ad i campi dell’oggetto corrente. E’ il primo parametro di
ogni metodo della classe, ma non deve essere passato dal
chiamante.
class Point:
def distance(self, other):
…
p= Point(10,20)
p1=Point(20,30)
p.distance(p1) => NON: p.distance(p,p1)!!
Classi ed Oggetti
 Come in altri linguaggi ad oggetti, e’ possibile fare
overloading di operatori built-in (es. addizione,
moltiplicazione, sottrazione, etc)
def __add__(self, other):
return Point(self.x+other.x,self.y+other.y)
Point p1=new Point(x1,y1)
Point p2=new Point(x2,y2)
p3=p1 + p2
Classi ed Oggetti
 Come in altri linguaggi ad oggetti, e’ possibile creare
gerarchie di classe tramite l’ereditarieta’.
 Come C++, Python supporta l’ereditarieta’ multipla.
 Per indicare che la classe Point3D e’ figlia della
classe Point:
class Point3D(Point):
Classi ed Oggetti
Esistono alcuni metodi di classe “speciali”:
•
__repr__ ritorna una rappresentazione di un
oggetto sotto forma di una stringa
• __cmp__ e’ utilizzato quando si effettua il confronto tra
classi (overloading dell’operatore ==)
• __len__ ritorna la lunghezza dell’oggetto
• __delitem__ richiamato da del istanza[chiave]
Classi ed Oggetti
 E’ possibile definire metodi privati che non possono
essere referenziati all’esterno della classe.
 La distinzione tra metodi pubblici e metodi privati si
basa esclusivamente sul nome.
 Se il nome di un metodo o attributo inizia con (man non
finisce con) due underscore, e’ privato; ogni altra cosa
e’ pubblica.
def __myfunction():
Classi ed Oggetti
 Come in Java/C++, Python consente la manipolazione
delle eccezioni tramite I blocchi try…except
 Il comando raise viene usato per lanciare
un’eccezione.
try:
fsock=open(“file.dat”,”r”)
except IOError:
Classi ed Oggetti
 (ES12) Indicare l’output del programma seguente.
import copy
class Obj:
pass
def fun(p):
p2=copy.copy(p)
if (p2.b==7):
p2.b=10
else:
p3.a+p3.b
p2.a=4
return p2
p=Obj()
p.a=5
p.b=7
p2=p
p2.b=5
p3=fun(p)
print
Classi ed Oggetti
 (ES13) Implementare una classe Stack
con I metodi push, pop e is_empty.
Classi ed Oggetti
class Stack:
# Class initializer
def __init__(self):
self.values=[]
# Push a value on top of the stack
def push(self,value):
self.values.append(value)
# Return the value on top
def pop(self):
if len(self.values) > 0:
return self.values.pop()
else:
raise ValueError
# Check if there are elements in the stack
def is_empty(self):
return (len(self.values) == 0)
Iteratori
 Tutti I tipi di sequenza incorporati in Python supportano
gli iteratori tramite ciclo for.
for value in sequence:
DO SOMETHING
 E’ possibile costruire degli iteratori su classi arbitrarie
definendo I seguenti metodi:
- __iter__(): restituisce l’oggetto iteratore
- next(): restituisce l’elemento successivo
Iteratori
 (ES14)
Implementare
la
classe
CircularQueue
che consente di
definire delle liste circolari in Python.
Iteratori
# Implements a Circular Queue
class CircularQueue:
def __init__(self,values):
self.values=values
def __iter__self(self):
return self
# Iterator function
def next(self):
if (len(self.values) > 0):
self.values=self.values[1:] + [self.values[0]]
return self.values[-1]
else:
raise ValError
Iteratori
 (ES15) Implementare la classe Tree
che consente di costruire degli alberi
(generici). Definire un iteratore della
classe che consente di fare visite in
profondita’ dell’albero.
Iteratori
 Un iteratore puo’ essere utilizzato per generare
sequenze di valori.
 Un valore viene prodotto su richiesta quando necessario.
 La sequenza di valori puo’ essere infinita.
 (ES16) Definire tramite iteratori la classe Factorial
che costruisce la sequenza dei fattoriali 1!, 2!, 3!, 4! …
etc
Iteratori
class Factorial:
def __init__(self):
self.fact=0
self.val=1
def __iter__(self):
return self
def next(self):
(self.val,self.fact,oldval)=(self.val*(self.fact+1),self.fact+1,
self.val)
return oldval
for i in Factorial():
print i
if i>30:
break
Generatori
 Un generatore e’ un’entita che genera iteratori.
 Un generatore e’ una funzione che si richiama
ripetutamente: ogni volta che viene richiamata,
l’esecuzione non ricomincia da capo, ma dal punto di
codice in cui la precedente chiamata ha restituito un
valore.
 Il comando yeld specifica il punto in cui un
generatore deve ritornare un valore.
Generatori
 (ES17) Indicare l’output del programma seguente.
def gen():
val=2
while:
yeld val
val=val*2
count=0
for i in gen():
if (count >=10):
break
else:
print i
count+=1
Generatori
 (ES18) Scrivere una funzione generatrice di numeri
primi (usando i generatori di Python).
Generatori
def prime_num():
n=2
prime=[]
while True:
if not[f for f in prime if n%f ==0]:
yield n
prime.append(n)
n=n+1
# Print out all the prime numbers <100
for i in prime_num():
if (i> 100):
break
print i
Generatori
 (ES19) Scrivere una funzione permutation(li)
che genera tutte le possibili permutazioni di una lista
presa in input
>> permutation([1,2,3])
>> [[1,2,3],[1,3,2],[2,3,1][2,1,3],[3,1,2],[3,2,1]]
Generatori
def permutation(list):
if len(list)<=1:
yield list
else:
for i in range(0,len(list)):
for tail in permutation(list[:i] + list[i+1:]):
yield [list[i]] + tail
for i in permutation([1,2,3,4]):
print i
Generatori
 (ES20) Scrivere una funzione powerset(li) che
prende in input una lista e stampa tutti i possibili
sottoinsiemi della lista (insieme potenza).
>> power_set([1,2,3])
>> [[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
Generatori
def powerset(li):
if len(li) <=1:
yield li
yield []
else:
for item in powerset(l[1:]):
yield [li[0]] + item
yield item
for i in powerset([1,2,3]):
print i
Moduli e Librerie
 Il modulo os dispone di molte funzioni utili per
manipolare file e processi.
 listdir(path) ritorna il contenuto di una directory
(in una lista).
 chdir(path) cambia la directory corrente a path
 chmod, chown, mkdir, rmdir, getcwd(), mknod() …
 getlogin(), getpid(), getuid(), getppid(), …
Moduli e Librerie
 Il modulo os dispone di molte funzioni utili per
manipolare file e processi.
import os
print "Current directory is ",os.getcwd()
print "Current login is ",os.getlogin()
print "Current Process id is ",os.getpid()
Moduli e Librerie
 (ES21)
Scrivere un programma che fa
scanning della rete, nel range di indirizzi da
192.168.100.60 a 192.168.100.70. A ciascuna
macchina della rete devono essere inviati 2
pacchetti ping, ed in base all’esito del comando
il programma deve visualizzare il messaggio:
“No response” o “Alive”.
Moduli e Librerie
import os
import re
import time
import sys
lifeline = re.compile(r"(\d) received")
report = ("No response","Partial Response","Alive")
print time.ctime()
for host in range(60,70):
ip = "192.168.100."+str(host)
pingaling = os.popen("ping -q -c2 "+ip,"r")
print "Testing ",ip, sys.stdout.flush()
while 1:
line = pingaling.readline()
if not line: break
igot = re.findall(lifeline,line)
if igot:
print report[int(igot[0])]
print time.ctime()
Programmazione di Rete
 Il modulo socket implementa i costrutti
principali per la programmazione di rete tramite
socket (C-like).
 socket(family,type) crea un nuovo socket
family: AF_UNIX, AF_INET, AF_INET6
type: SOCK_STREAM (tcp), SOCK_DGRAM(udp)
Programmazione di Rete
 bind(host, port): collega il socket ad un
host name e ad una porta specificata
 accept(): accetta connessioni da un client.
Restituisce: (nuovo socket per comunicare con
il client, indirizzo del client)
 send(), recv(): inviano/ricevono dati
 close(): chiude il socket
Programmazione di Rete
 (ES22)
Scrivere
una
semplice
applicazione di rete Client-Server. Il client
resta in attesa di ricevere un messaggio
da tastiera e lo spedisce al Server, che lo
stampa a video.
Programmazione di Rete
import socket
class SocketClient:
def __init__(self,host, port):
size=1024
while True:
message="Insert a message to send "
read=raw_input(message)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host, port))
s.send(read)
s.close()
message="Insert Q to exit … "
read=raw_input(message)
if (read == "Q"):
break
sc=SocketClient("localhost",5000)
Programmazione di Rete
import socket
class ServerSocket:
def __init__(self):
self.host="localhost"
self.port=5000
self.size=1024
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((self.host,self.port))
s.listen(5)
while True:
client, address = s.accept()
data = client.recv(self.size)
print " [SERVER ECHO] Receiving data from ",address," Message: ",data
client.close()
ss=ServerSocket()
Programmazione di Rete
 select(input,
output,
exception,
[timeout]): gli argomenti sono liste di socket che
attendono per input/output/eccezioni.
 La chiamata della select e’ bloccante se timeout non e’
impostato
 Ritorna una tupla di tre liste: sottoinsieme dei socket in
input che hanno input/output/eccezioni.
Programmazione di Rete
 (ES23) Modificare la configurazione del
Server dell’esercizio ES21 in modo che
sia in grado di gestire piu’ connessioni in
ingresso dai Client tramite la select.
Programmazione di Rete
class ServerSocket:
def __init__(self):
self.host="localhost"
self.port=5000
self.size=1024
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((self.host,self.port))
server.listen(5)
input= [server]
while True:
inputready,outputready,exceptionready= select.select(input,[],[])
for c in inputread:
if (c==server):
client, address = server.accept()
input.append(client)
else:
data = c.recv(self.size)
c.close()
input.remove(c)
Programmazione di Rete
 TWISTED: framework per il networking che
consente di sviluppare applicazioni di rete in
Python
 Consente di creare: protocolli di rete, SMTP,
HTTP, SSH proxy, filtri di traffico, etc
 http://twistedmatrix.com/
Thread
 Il modulo threading offre una libreria di
funzioni per lavorare con i thread.
 Per creare un thread, occorre creare una
classe figlia di threading.Thread.
 Per avviare il thread, occorre eseguire il
metodo start.
 Il codice del thread e’ contenuto nel run.
Thread
 Thread diversi potrebbero avere necessita’ di
condividere strutture dati.
 METODO 1. => utilizzo del modulo Queue
 Implementa lock e metodi synchronized per
l’accesso a strutture condivise.
 Metodi: get, put, join, task_done, …
Thread
 (ES24)
Modificare l’esercizio E20 in modo da
suddividere l’operazione di scansione della rete
tra N thread.
Thread
import
import
import
import
import
import
os
re
time
sys
Queue
threading
lifeline = re.compile(r"(\d) received")
report = ("No response","Partial Response","Alive")
print time.ctime()
queue=Queue.Queue()
class ThreadScanner(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
Thread
def run(self):
while True:
host = self.queue.get()
ip = "192.168.100."+str(host)
pingaling = os.popen("ping -q -c2 "+ip,"r")
print "Testing ",ip, sys.stdout.flush()
while 1:
line = pingaling.readline()
if not line: break
igot = re.findall(lifeline,line)
if igot:
print report[int(igot[0])]
self.queue.task_done()
Thread
# List of Threads
for i in range(0,5):
t=ThreadScanner(queue)
t.start()
for host in range(60,70):
queue.put(host)
queue.join()
print time.ctime()
Thread
 Oltre al modulo Queue, Python mette a
disposizione i tradizionali meccanismi di
sincronizzazione per l’accesso a strutture dati
condivise:
 Lock: metodi acquire – release
 Re-Entrant Lock (RLocks)
 Semafori