home page::doc::intro
Mimante.net

Avviso!

Questo articolo è basato su una versione obsoleta di python; può ancora essere utile come tutorial basilare, ma non copre le molte features introdotte nel corso degli ultimi anni.

Perché un altro linguaggio?

Già mi sembra di sentirvi urlare disperati: "Noo! Perché un altro linguaggio?", peggio: "Perché un altro linguaggio interpretato?". Forse non avete tutti i torti ma, a parte semplicistiche considerazioni stile "meglio uno di più che uno di meno", vedrete che se concederete una possibilità a python1 (http://www.python.org) ve ne innamorerete facilmente.

Ok, cosa sarebbe questo python?

Python è nato tra il 1989 e il 1990 ad opera di Guido Van Rossum che aveva già lavorato all'elegante linguaggio ABC, di scarsa fortuna. Python è un linguaggio interpretato (in verità pseudocompilato, ma non formalizziamoci 2) con alcune caratteristiche che lo rendono molto interessante; vediamone un elenco:

I vantaggi

In confronto ai linguaggi compilati i pregi di un interpretato sono evidenti: il tempo richiesto dal ciclo di sviluppo è inevitabilmente molto minore, il programma è facilmente modificabile ed inoltre è portabile su tutte le piattaforme per cui esiste l'interprete; per contro un interpretato paga queste qualità in termini di velocità di esecuzione, ma questo normalmente non rappresenta un grave problema per la maggior parte dei programmi.
Nel campo degli interpretati la lotta è di certo più agguerrita e Python si scontra con i semplici script di shell come bash e tcsh che però risultano subito troppo lenti e poco potenti per progetti di una certa complessità e i due linguaggi di script di maggior successo: il Perl e il Tcl; tra questi il Python è di certo quello meno diffuso, ma di sicuro in questi ultimi anni si sta guadagnando molta popolarità, e sul piano della programmazione non ha nulla da invidiare ai diretti concorrenti essendo stato creato proprio cercando di prendere il meglio dai vari linguaggi disponibili.

Let's start with code!

A questo punto, sperando di non spaventarvi troppo, presento subito il codice di un piccolo script che tutto sommato fa cose non poi così piccole (fatelo in C con tutti i controlli del caso e fatemi sapere quante righe sono): le righe qui sotto si collegano al server POP-3 mail.ginopino.it (che spero non esista!) e controlla ogni 10 minuti se c'è posta per noi, nel qual caso stampa a video il numero di messaggi e la loro dimensione totale.
#!/usr/bin/python
# questo è un commento inutile :-)

import poplib, sys, time

def controlla_posta():
    """Funzione che controlla una casella di posta"""
    try:
        connessione = poplib.POP3('mail.ginopino.it')
        connessione.user('davide')
        connessione.pass_('la_mia_password')
        nmex, sz = connessione.stat()
        connessione.quit()
        return nmex, sz
    except (poplib.socket.error, poplib.error_proto), messaggio:
        print 'Oh-oh, un problema:', messaggio
        sys.exit(1)

while 1:
    try:
        numero_messaggi, dimensione = controlla_posta()
        if numero_messaggi > 0:
            print 'Numero messaggi:', numero_messaggi, 'Dimensioni:', dimensione
        time.sleep(600)
    except KeyboardInterrupt:
        print 'Lieto di essere stato utile!'
        sys.exit(0)

Dottore! Questo codice sta male!

E allora smontiamolo pezzo per pezzo e analizziamolo...

linea 1 |  #!/usr/bin/python
linea 2 |  # questo è un commento inutile :-)

Come ogni script anche i programmi python devono iniziare con il classico #! sulla prima riga seguito dal percorso dell'interprete. In Windows questa riga è ignorata, ed è importante che il file abbia estensione .py e che questa sia associata all'interprete. Il codice python può contenere commenti che andranno fatti precedere da #.

Come noterete da questo esempio i vari blocchi di codice in python non sono delimitati, come in molti altri linguaggi, da parentesi di qualche sorta o delimitatori di begin/end; l'interprete determina l'inizio e la fine dei vari blocchi usando l'indentazione (il numero di spazi o tab dall'inizio della riga): una volta aperto un nuovo blocco di codice (ad esempio per la dichiarazione di una funzione, per l'inizio di un ciclo o di una condizione if) la riga successiva dovrà essere indentata in modo più profondo della precedente e, una volta giunti alla fine del blocco di istruzioni (fine della definizione, del ciclo, dell'if...), si dovrà tornare ad allineare il codice allo stesso livello delle istruzioni precedenti. In questo modo il codice python risulta molto compatto e leggibile (in pratica costringe il programmatore a seguire un buono stile di scrittura); un buon consiglio può essere quello di usare sempre quattro spazi come tabulazione: il programma ne guadagnerà decisamente in estetica; la maggior parte degli editor di testo dovrebbero essere in grado di farvi settare il tab e di sostituirlo automaticamente con il corrispondente numero di spazi.


linea 3 |  import poplib, sys, time

L'istruzione import importa i moduli specificati; in questo caso i moduli standard poplib per la gestione di caselle di posta POP-3, sys che contiene molte variabili ed alcune funzioni che interagiscono con l'interprete e con il sistema e time che gestisce funzioni e variabili riferite alla gestione del tempo e della data.

Un modulo è un file contenente definizioni e altre istruzioni python; il file che contiene il modulo deve avere estensione .py e viene importato chiamandolo con nome del file privo di estensione. Ogni modulo ha la sua tabella di simboli privata, questo significa che ogni funzione ed ogni variabile definita in un modulo non è direttamente visibile nel programma che lo include, ma per riferirsi agli oggetti che contiene sarà necessario usare una sintassi del tipo: nomemodulo.nomeoggetto
import accetta anche un paio di varianti della sua sintassi; la prima è:

from nomemodulo import oggetto1 oggetto2
che importa solo gli oggetti oggetto1 e oggetto2 dal modulo nomemodulo; mentre la seconda:
from nomemodulo import *
importa tutti gli oggetti da nomemodulo; in entrambi i casi gli oggetti importati saranno direttamente disponibili nello script (ad esempio sarà possibile riferirsi direttamente a oggetto1). Ovviamente queste ultime due sintassi possono essere utilizzate solo se non si andranno a creare conflitti con i nomi di variabili, classi, funzioni o altro specificato nel codice che va ad importare gli oggetti da moduli esterni; di norma la documentazione di un modulo indica se è o meno possibile procedere in questo modo.
Vi starete chiedendo come python trova i file che corrispondono ai moduli; è piuttosto semplice: prima di tutto cerca nella directory corrente un file di nome nomemodulo.py, se non è presente cerca il file nelle directory specificate nella variabile d'ambiente $PYTHONPATH, se questa non è settata o il modulo non è stato ancora trovato la ricerca continua in alcune directory di default dipendenti dal sistema operativo usato (in unix ".:/usr/local/lib/python"); se ancora il modulo non è stato trovato, verrà generata una eccezione di tipo ImportError (delle eccezioni ci occuperemo tra breve, non preoccupatevi). Alcuni dei moduli che abbiamo importati sono built-in nell'interprete python (e quindi sempre disponibili), mentre altri sono distribuiti in normali file (provate a cercare nella directory /usr/lib/python1.5), ma all'atto pratico questi due tipi di moduli sono assolutamente equivalenti.
Python dispone di un numero piuttosto elevato di moduli standard con un numero impressionante di funzioni già pronte: grazie a questi i vostri programmi potranno compiere azioni piuttosto complesse in poche righe. Documentazione estesa sui moduli standard può essere trovata sulla "Python Library Reference" che consiglio di tenere sempre a portata di mano.

linea 4 |  def controlla_posta():
linea 5 |  """Funzione che controlla una casella di posta"""

Qui definiamo la funzione controlla_posta() che non riceve alcun argomento e restituirà due interi.

L'istruzione def consente di definire una nuova funzione. La stringa sotto, racchiusa tra due coppie di tre doppiapici è la docstring che descrive brevemente lo scopo della funzione; deve essere di una riga sola ma può essere seguita da uno spazio vuoto e da una nuova docstring anche su più righe per descrizioni più dettagliate; le docstring sono usate per creare documentazione in automatico, quindi è buona abitudine usarle (eventualmente tornerò sull'uso delle docstring in un ipotetico capitolo sullo stile di scrittura).
Una volta che la funzione verrà eseguita ci troveremo in un nuovo spazio di simboli, quindi tutte le variabili e gli oggetti che verranno qui definiti non saranno direttamente visibili dal codice che ha chiamato la funzione stessa.
Alle funzioni è possibile passare argomenti, semplicemente elencandoli tra le parentesi separandoli con virgole; è anche possibile assegnare valori di default ad uno o più argomenti, ad esempio:

def prova(primo, secondo=3, terzo='Ciao'):
    print terzo, secondo * primo
che potrà essere chiamata, indifferentemente con:
prova(2)
prova(2, 4)
prova(3, 5, 'Test')
Invocazioni che avranno come rispettivo output:
Ciao 6
Ciao 8
Test 15
Inutile sottolineare che chiamare la funzione con:
prova()
si genererà un errore essendo presente nella dichiarazione della funzione almeno un argomento a cui non è stato assegnato un valore di default. L'errore sarà una eccezione TypeError che indicherà la riga in cui è avvenuto l'errore e una sua breve descrizione:
Traceback (innermost last):
  File "./test", line 6, in ?
    prova()
TypeError: not enough arguments; expected 1, got 0
È anche possibile definire una funzione che raccolga un numero variabile di argomenti:
def prova2(primo, secondo, *altri)
Dove tutti gli argomenti oltre il secondo verranno assegnati ad una tuple (un tipo di dati consistente in un numero variabile di oggetti qualsiasi, una specie di lista; sui vari tipi di dati torneremo nel prossimo articolo).
Altra possibilità interessante è l'uso di argomenti keyword: in pratica è possibile invocare normalmente la funzione, ma nei valori di chiamata si passeranno delle coppie keyword: valore. Facciamo un esempio:
def funzione(primo, key1='gatto', key2='cane')
Si potrà chiamare questa funzione indistintamente con:
funzione(42)
funzione(0, key2='mucca')
funzione(3, key1='balena', key2='scimmia')
Mentre saranno errare le chiamate:
funzione()                # almeno un argomento (primo)
funzione(key3='branzino')  # keyword non nota
funzione(primo=0, 'verme') # variabile non keyword dopo una keyword
funzione(primo=0, 4)      # doppio valore assegnato ad una variabile
Un parametro della forma **keywords raccoglierà tutte le keyword passate come argomenti non ancora assegnate in un dizionario (altro tipo di dati composto da un insieme di coppie di keyword e valori); se questo parametro è usato insieme alla forma per raccogliere parametri multipli **keywords deve necessariamente seguire *argomenti: quest'ultimo raccoglie gli argomenti non-keyword in sovrappiù, mentre a **keywords verranno assegnate le coppie keyword:valore extra.
Da ricordare che in tutti i casi i valori di default passati ad una funzione sono valutati prima che entri in esecuzione la funzione stessa, sono quindi consentite perversioni del tipo:
variabile = 42
def funzione(primo, secondo=variabile, terzo=1):

Ma continuiamo ad analizzare il codice:


linea 6  |  try:
              .
              .
              .
linea 13 |  except (poplib.socket.error, poplib.error_proto), messaggio:

Creiamo una zona sottoposta al controllo delle eccezioni poplib.socket.error e poplib.error_proto.

Eccezioni ed errori di sintassi sono il modo che python ha di farci capire che qualcosa è andato storto: gli errori di sintassi si hanno quando il parser non riesce ad interpretare quello che abbiamo scritto: può essere dovuto ad una parentesi non chiusa o ad una virgola al posto sbagliato; in questo caso l'interprete interrompe la lettura del codice ed esce stampando a video il punto in cui è stato incontrato il problema. Le eccezioni invece vengono lanciate quando una istruzione corretta ha incontrato un problema (per esempio una divisione per zero, ma la casistica è molto più ampia). Le eccezioni possono essere catturate includendo la parte di codice che si pensa possa generarle nella coppia di istruzioni try: except:
Se una eccezione non viene catturata provocherà l'interruzione del programma e conseguente stampa di un messaggio di errore. In breve funziona così:

Se fosse necessario scrivere codici diversi a seconda dell'eccezione generata, ad una istruzione try possono essere associate più istruzioni except, ad esempio:
try:
  .
  .
  .
except IOError, messaggio:
    print 'Errore di input/output:', messaggio
except ZeroDivisionError, messaggio:
    print 'Divisione per zero:', messaggio
Se l'istruzione except non ha nessun argomento tutte le eccezioni sono catturate: questa possibilità va usata con estrema cautela, essendo possibile che nasconda reali problemi del programma. Molte eccezioni hanno associate un valore sotto forma di stringa usato per fornire una descrizione dettagliata di ciò che è successo: questo valore può essere catturato semplicemente ponendo come secondo argomento di except la variabile che lo conterrà (nel nostro esempio messaggio). Al posto dell'istruzione except è possibile usarne un'altra dal comportamento diverso: finally. Il codice dell'istruzione finally è eseguito sia che venga lanciata o meno una eccezione; dopo l'esecuzione di questo codice l'eccezione viene nuovamente lanciata e se non catturata da istruzioni except di livello superiore il programma esce (in pratica è utile per scrivere una volta sola alcune righe di codice che devono necessariamente essere eseguite anche nel caso il programma incontri un errore).
Ultima nota da segnalare per quanto riguarda la raccolta di una eccezione è che in caso questa venga generata in una parte di codice esterna alle istruzioni try/except o try/finally (ad esempio in una funzione chiamata) queste non vengono catturate.
È possibile per l'utente lanciare una eccezione con l'istruzione:
raise nomeEccezione, 'Descrizione'
dove nomeEccezione è chiaramente il nome dell'eccezione da lanciare e Descrizione è l'eventuale argomento.
Se ne ha necessità il programmatore può anche definire le proprie eccezioni; il modo più semplice è definire l'eccezione come una stringa la quale sarà usata come messaggio di errore. Esempio banale:
nuovoError = 'Il programma ha incontrato un problema'
raise nuovoError
Dalla versione 1.5 in python le eccezioni sono state riscritte per essere classi; è ancora possibile utilizzare la vecchia sintassi vista sopra, ma è preferibile seguire il nuovo design. Tutte le eccezioni standard sono state inquadrate in un albero logico nel modulo exceptions alla base del quale c'è la classe Exception dal quale l'utente può far derivare le proprie eccezioni in questo modo:
class MyError(Exception):
    """Mia classe di errori"""
    pass
Da questa è possibile creare istanze:
primotipoError = MyError('Un tipo di errore')
Che potrà essere invocato con le forme equivalenti:
raise primotipoError
raise MyError, primotipoError
raise MyError(primotipoError)
Non è comunque obbligatorio derivare oggetti dalla classe; sono perfettamente lecite le chiamate:
raise MyError()
raise MyError('Un altro tipo di errore')
Di queste varie forme è preferibile utilizzare raise nomeIstanza o raise NomeClasse(argomenti); ultima cosa da ricordare è che la classe indicata nell'istruzione except blocca anche tutte le classi da questa derivate (ma non la classe o le classi da cui deriva).
Per maggiori informazioni sulle caratteristiche e sulla organizzazione delle eccezioni rimando alla documentazione del già citato modulo exceptions; sulle classi e loro proprietà torneremo nel prossimo articolo.

linea 7 |  connessione = poplib.POP3('mail.ginopino.it')

Creiamo una istanza dell'oggetto POP3.

Nelle librerie standard del python vi sono numerose definizioni di classi dalle quali è possibile derivare oggetti manipolabili con semplicità; per creare un nuovo oggetto è sufficiente la sintassi nomeoggetto = Classe() racchiudendo tra le parentesi eventuali argomenti richiesti. Nel nostro esempio abbiamo creato un oggetto chiamato connessione partendo dalla classe POP3 definita nel modulo poplib che richiedeva come argomento una stringa rappresentante il nome di un server di posta.


linea 8 |  connessione.user('davide')
linea 9 |  connessione.pass_('la_mia_password')

Richiamiamo dei metodi propri dell'oggetto sopra creato: in pratica ci connettiamo al server stabilito durante la creazione dell'oggetto connessione e inviamo in sequenza i comandi per identificarci come utente davide e per passargli la nostra password.

Una volta creato un oggetto è possibile sia manipolarne eventuali variabili sia eseguirne funzioni (dette in questo caso metodi) definite all'interno della classe a cui l'oggetto appartiene. Sempre con un occhio al nostro esempio abbiamo la successiva chiamata dei metodi user() e pass_() dell'oggetto connessione definiti nella classe POP3; in questo caso entrambi i metodi non hanno alcun valore di ritorno e richiedono un solo argomento.


linea 10 |  nmex, sz = connessione.stat()

Raccogliamo delle statistiche fornite dal mail server che raccoglie la nostra posta.

Come era logico aspettarsi molti metodi restituiscono argomenti che possiamo raccogliere assegnandoli ad una variabile; un metodo o una funzione può restituire anche più di un argomento: in questo caso possiamo decidere di raccogliere i vari argomenti in variabili separate o in una sola sotto forma di tuple; in ogni caso è sempre possibile ignorare il valore di ritorno di una funzione semplicemente non raccogliendone il risultato.
Come avrete notato le variabili non sono tipizzate e possono essere dichiarate al momento dell'uso.


linea 11 |  connessione.quit()

Chiudiamo la connessione al server.

linea 12 |  return nmex, sz

La nostra funzione controlla_posta() restituisce i due valori raccolti dal server.

Una funzione può restituire uno o più valori semplicemente usando l'istruzione return seguita dai valori di ritorno. Una funzione che non comprenda un return non restituisce alcun valore (o meglio, restituisce None, oggetto non troppo diverso dal NULL del C/C++) è comunemente chiamata procedura.


linea 16 |  while 1:

Iniziamo un ciclo infinito.

Come avrete notato dall'indentazione di questa istruzione il codice inizia ad essere eseguito proprio da questo punto, essendo l'istruzione che la precede allo stesso livello (def controlla_posta():) una definizione di funzione, la quale ovviamente non viene eseguita immediatamente ma solo quando esplicitamente richiamata.
A questo punto mi sembra d'obbligo addentrarci in un paio di argomenti importanti: i valori di verità e le istruzioni classiche della programmazione strutturata.

La verità è là fuori!

A costo di dire una banalità definiamo vero in python tutto ciò che non è falso. Per farla breve ecco un elenco di ciò che è falso: Tutti gli altri oggetti, variabili e classi sono da ritenersi veri.

Il mio float è più grande del tuo!

Su tutti gli oggetti è possibile utilizzare i tipici operatori booleani; vediamone la sintassi: È importante specificare che gli operatori or e and ritornano sempre uno degli oggetti su cui sono eseguiti (or restituirà x se questo è vero altrimenti restituirà y; and restituisce x se questo è falso, altrimenti y).

Su tutti gli oggetti sono anche possibili confronti; i più comuni sono: < minore stretto, <= minore uguale, > maggiore, >= maggiore uguale, == uguale, != o <> diverso e l'operatore is che ritorna vero se l'oggetto specificato è del tipo richiesto (la sua negazione è is not). Questi operatori restituiscono sempre 0 per indicare falso e 1 per indicare vero.
Sono possibili anche confronti tra tipi diversi (per esempio una stringa ed una lista), ma il loro output è chiaramente arbitrario.
Probabilmente vi state chiedendo come possano essere utilizzati gli operatori is e is not che in molti casi possono tornare davvero comodi; per farlo dobbiamo importare gli oggetti definiti nel modulo standard types in questo modo:

from types import *
A questo punto sarà possibile usare la funzione type() sull'oggetto di cui ci domandiamo la natura e confrontarne l'output tramite gli operatori is o is not con le definizioni di tipo importate dal modulo types. Ad esempio:
if type(variabile) is IntType:
    print 'la variabile è un intero'

if (no, Kipling non c'entra)

L'istruzione if funziona esattamente come ci si potrebbe aspettare; un esempio di codice dovrebbe essere sufficiente a chiarirne l'uso:

if variabile > 1:
    print 'la variabile è maggiore di 1'
# possono essere presenti zero o più elif, contrazione di else if
elif variabile == 3:
    print 'la variabile vale 3'
else:
    print 'la variabile vale', variabile

while (cicli)

Lo abbiamo visto: ripete il ciclo finché la condizione resta vera.
Nei cicli while e for (che analizzeremo qui sotto) è possibile usare le istruzioni break e continue che rispettivamente fanno uscire dal ciclo e interrompono l'attuale iterazione del ciclo per riprenderlo dall'inizio con l'iterazione successiva. Altra istruzione interessante da applicare a questi due cicli è else il cui codice viene eseguito quando la condizione di un ciclo while diventa falsa o quando viene esaurita la lista di un ciclo for (in ogni caso questo codice non verrà eseguito se si esce dai cicli con un break). Piccolo esempio:
x = 0
while x < 10:
    x = x + 1
else:
    print 'x è ora maggiore di 10'

for (iterazioni)

I cicli for vengono ripetuti per ogni oggetto della sequenza passata come argomento, assegnando alla variabile specificata il valore dell'oggetto. Questo comportamento è piuttosto diverso da quello del C o del Pascal e simile a quello del for nella shell bash. Un esempio chiarificatore:
for variabile in 'cane', 'gatto', 4, 5:
    print 'Variabile:', variabile
avrà come output:
Variabile: cane
Variabile: gatto
Variabile: 4
Variabile: 5

pass

Indica di non fare nulla: può essere usato in qualsiasi parte del programma (all'interno di classi, di funzioni, di cicli, etc.) dove la sintassi richieda una espressione ma non sia necessario compiere alcuna azione.
def tipica_procedura_Microsoft():
    """Non fa assolutamente nulla e non è documentata ;-)"""
    pass

linea 17 |  try:
              . 
              .
              .
linea 22 |  except KeyboardInterrupt:

Catturiamo il ctrl+c.

Ricominciamo ora ad analizzare il codice del nostro piccolo esempio: abbiamo già visto le istruzioni try/except, qui le applichiamo allo stesso modo ora che siamo dentro un ciclo infinito in cui l'unico modo per uscirne (a meno di altri errori nel funzionamento del programma o del collegamento al server) è l'uso della combinazione ctrl+c che uccide il processo corrente. Naturalmente il programma verrebbe ugualmente terminato se non catturassimo questo interrupt, ma in quel caso verrebbe stampata a video l'indicazione dell'eccezione generata, e non è certo piacevole da vedere; grazie a questa istruzione except invece possiamo chiudere il programma con un messaggio di saluto e chiamando poi la funzione exit() del modulo sys che serve a chiudere con delicatezza il programma specificando un valore di ritorno.
C'è da notare una questione piuttosto subdola già accennata durante la trattazione delle eccezioni e che qui vediamo nella pratica: con ogni probabilità quando premeremo ctrl+c il programma starà eseguendo l'istruzione sleep, ma se per pura sfortuna cercassimo di chiuderlo mentre il programma sta eseguendo la chiamata alla funzione controlla_posta() vedremmo comparire a video il messaggio di errore dell'eccezione, non essendo questa catturata anche durante l'esecuzione della funzione stessa; se volessimo migliorare il codice potremmo sostituire nella riga 13 (poplib.socket.error, poplib.error_proto) con (poplib.socket.error, poplib.error_proto, KeyboardInterrupt).


linea 18 |  numero_messaggi, dimensione = controlla_posta()

Chiama la funzione controlla_posta() precedentemente definita e immagazzina i valori di ritorno nelle variabili numero_messaggi e dimensione di chiaro significato; non credo ci sia altro da dire su questo passaggio, essendo argomenti già trattati.

linea 19 |  if numero_messaggi > 0:

Se il numero dei messaggi indicato dal server è maggiore di 0, allora...

linea 20 |  print 'Numero messaggi:', numero_messaggi, 'Dimensioni:', dimensione

Stampa il numero di messaggi e la dimensione in byte dei messaggi nella nostra casella.

print

Vale la pena spendere due parole in più sulla funzione print in quanto capiterà certamente spesso di dover stampare un risultato sullo schermo. La forma vista finora:
print argomento1, argomento2, ...
è utile per alternare stringhe con numerici e altri tipi di dati, ma non si presta molto bene per output più complessi (di cui spero di parlare nel prossimo articolo) in cui spesso è necessario prima convertire valori numerici in stringhe racchiudendoli tra `apici singoli inversi` e concatenare due stringhe senza lasciare uno spazio tra loro, effetto ottenibile sostituendo le virgole che separano gli argomenti con un +. Se è necessario inserire il risultato di una funzione è possibile usare anche una sintassi più chiara con non la separazione degli argomenti tramite virgole:
print 'Prima funzione: %s Seconda funzione: %s' % (funz1(), funz2())
Dove %s è un segnaposto per il risultato della funzione.
Oltre che da apici singoli le stringhe possono anche essere racchiuse tra doppi apici; in entrambi i casi i caratteri speciali vanno scritti tramite le classiche sequenze di escape (ad esempio il ritorno a capo sarà \n). Se si vuole un output su più linee senza dover scrivere caratteri di escape è possibile racchiudere la stringa tra tripli doppi apici, ad esempio:
print """stringa molto
lunga con a capo"""
Come avrete notato in ogni caso print aggiunge un ritorno a capo finale; se fosse necessario un controllo più fine sull'output si dovrà usare il metodo write sui descrittori di file stdout e stderr definiti nel modulo sys. Ad esempio (notate che il ritorno a capo è stato scritto esplicitamente):
sys.stdout.write('Output su standard output\n')
sys.stderr.write('Output su standard error\n')

linea 21 |  time.sleep(600)

Invoca sleep definita nel modulo precedentemente importato time; questa procedura sospende l'esecuzione del programma per lo specificato numero di secondi (può ricevere anche un float, se è necessaria una precisione maggiore).

A questo punto, se il programma non è stato interrotto dall'utente o da un qualche errore, il ciclo while riprenderà nuovamente fino alla fine del mondo o allo spegnimento del computer.

Conclusioni e prossimi capitoli

Finisce qui l'introduzione a python; spero abbiate ora una vaga idea di come funziona e basi sufficienti per scrivere alcuni piccoli script. Non crediate però che sia tutto qui: come detto nella presentazione python è un linguaggio ad oggetti adatto anche per progetti di notevoli dimensioni; nella prossima puntata (no, non ho idea di quando sarà pronta) mi inventerò un programma ad oggetti in cui si faccia uso di classi, input/output da/su file e tastiera, tipi di dati complessi e chissà cosa altro mi verrà in mente.
Se avete idee molto brillanti su quali argomenti dovrei trattare, come farlo, spunti interessanti e commenti a questo articolo contattatemi pure a alberanid@libero.it.

Altra documentazione e link

Tutta la documentazione che vi serve dovrebbe già essere presente sul vostro sistema nella directory /usr/doc/python o /usr/share/doc/python; molto utile il Tutorial e fondamentale la Library Reference dove sono descritte dettagliatamente tutte le librerie standard. Nella sottodirectory examples vi sono numerosi script da cui potrete prendere spunto (attenzione: la documentazione e gli esempi potrebbero essere in pacchetti separati di nome python-doc e python-examples).
Per quanto riguarda i link, per ora non vi è molto di specifico da segnalare se non:

Note

1 - Prima che ci perdiate il sonno: il nome deriva dai mitici Monty Python e non ha nulla a che fare con i rettili.
2 - Ok, formalizziamoci: come di certo saprete nei linguaggi compilati (come il C) il sorgente è elaborato da un compilatore che si occupa di crearne codice eseguibile sull'architettura target; i programmi dei linguaggi interpretati (Basic, bash) vengono invece letti ed eseguiti una linea alla volta: ciò risulta molto lento e quindi poco adatto a programmi complessi; per ovviare a questi inconvenienti nei linguaggi pseudocompilati il codice viene letto completamente sin dall'inizio e ne viene creata al volo una "immagine" in un linguaggio intermedio tra il solo testo dello script ed il codice dipendente dall'architettura; l'interprete eseguirà poi questo pseudocodice in maniera molto più veloce che leggendo lo script line per linea.
3 - Python è già disponibile per molte versioni di Unix, DOS, Windows, Windows NT, OS/2, Mac, Amiga e altre piattaforme ancora.