MyPython
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Introduzione Linguaggio interpretato (con creazione di un byte code intermedio) orientato ad oggetti.
Pro:
· · · ·
elegante e potente (soprattutto nel gestire testi/dati): rispetto ad altri linguaggi, spesso permette di ottenere gli stessi risultati con meno codice e pure più leggibile (ad esempio in due righe si riesce a contare il n. di occorrenze delle parole di un testo!) listati “ordinati” dato l'uso dell'indentazione come delimitatore di blocchi (alcuni lo “odiano” per questo: io no!) presenza di ottime librerie di base (gestione xml, pdf,…) , oltre a numerose altre opzionali (comprese quelle per le più comuni librerie grafiche) possibilità di applicazioni multi-piattaforma
Contro:
· avendo caratteristiche un po' personali, occorre del tempo per sfruttarne appieno la potenza · lento rispetto ad altri linguaggi C++, Delphi (in genere quelli compilati). · Per migliorare la situazione si può: o Adoperare librerie per compiti specifici (e.g. matematici) o Utilizzare il compilatore Psyco (che però fa occupare molta memoria) o Usare import NomeProgramma che costringe ad usare direttamente il bytecode (Python infatti ricompila ogni volta il source attuale, mentre usa il bytecode degli elementi dell' import )
o Il compilatore Py2Exe si limita ad appiccicare un interprete al programma: la sua utlità è solo per la
distribuzione, non la velocità. Chiaramente anche programmi brevi avranno una certa occupazione minima
o Nel futuro sperano in PyPy (un Python scritto in Python…non ho capito perchè, ma potenzialmente in futuro
· · · · · ·
· ·
dovrebbe essere molto efficiente) stringhe immutabili (abituato a Dephi, mi mancano….) case-sensitive, cioè distingue tra maiuscole e minuscole nei nomi dei comandi e delle variabili (fonte di tanti errori involontari, soprattutto se si usano librerie esterne tipo (WxPython o PyQt) in cui i comandi hanno regole diverse nelle varie versioni o rispetto al resto del Python) indici delle stringhe (”slicing”) che iniziano da zero ed il secondo indice indica il primo carattere escluso (solo talvolta torna utile: la maggior parte delle volte è solo scomodo e poco intuitivo) l'assegnazione di eguaglianza tra una variabile e l'altra le rende in realtà la medesima entità: fonte di grandi casini potenziali…occorre importare un modulo apposta per evitare questo problema gestione delle variabili globali diverso dal solito (nulla di difficile, ma occorre saperlo) manca il case/switch di altri linguaggi: è rimpiazzabile con il seguente codice (ma mi pare più un trucco, peraltro meno leggibile casi = {'a': funzione_per_a, ‘b': funzione_per_b, ‘c': funzione_per_c} # Dizionario che associa funzioni agli elementi di scelta casi[lettera]() Si richiama un dato elemento accedendovi tramite la chiave di scelta è ancora in cambiamento siamo alla transizione verso la 3.0 che non sarà completamente retro-compatibile inizia ad esserci qualche editor discreto (ad esempio PyScripter), ma si è lontani anni luce dagli ambienti IDE e RAD disponibili per Delphi o i vari Visual Microsoft
La maggior parte delle informazioni si riferiscono alla versione 2.6 (alla 3.0 verrà dedicata una sezione a parte).
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Regole del linguaggio Caratteristiche generali
· è tutto case-sensitive (comandi, variabili, funzioni…) con grande prevalenza del minuscolo. o i nomi dei metodi possono essere: § tutti minuscoli separati da underscore (e.g. my_app) § oppure con l'iniziale minuscola e le altre parole con prima lettera maiuscola [lowerInterCap] (e.g. · · · ·
myApp) i nomi di variabili/funzioni che iniziano per: o “_” (singolo underscore) significa che sono “pericolosi” o “__” (doppio underscore) non sono accessibili al di fuori della propria funzione/classe I metodi e le proprietà richiedono sempre le parentesi tonde (anche se vuote) print r.readline () [soprattutto nella versione 3.0] i blocchi sono indicati dall'indentazione le istruzioni che prevedono a seguire dei blocchi, terminano con due punti “:” if a==3: scrivendo un comando isolato, l'interprete ne dice il tipo con il comando help (comando) si ottiene la descrizione del comando con il comando dir (comando) si ottiene l'elenco dei metodi associati all'oggetto pass equivale a linea vuota (per prove con comandi che richiedono un blocco di istruzioni)
· · · · · None (con la "N" maiuscola) equivale al null di altri linguaggi · i commenti iniziano con il cancelletto # . Esiste poi una particolare forma di commento per gli oggetti (vedi DocStrings)
· si possono importare moduli con il comando import o usato come from Tkinter import * non occorre specificare ogni volta la libreria di riferimento nei comandi o con import Tkinter occorrerà invece precedere ogni comando con Tkinter.comando o una via di mezzo è import Tkinter as tk che permetterà di anteporre un nome più corto (in questo caso tk.comando )
Suddivisioni e blocchi
· Il punto e virgola “;” separa più comandi sulla stessa riga (deprecato) · Per estendere un comando su più righe si può: o usare lo slash ” \ “ o lasciare aperta una parentesi (tonda, quadra o graffa) Matematica
· · · · · · · · ·
= si usa per le assegnazioni di valori a variabili pippo=2 == si usa per i confronti di uguaglianza if pippo==2: (comunque avverte se si mette impropriamente un solo “=”) ! significa not != significa diverso (l'espressione <> , ora deprecata, mancherà in Python 3) ** significa “elevato a” la divisione (”/”) è di default intera (per cui 3/2 = 1, come in C). In Python 3.0 invece sarà non intera e darà 1.5 come risultato (la divisione intera sarà indicata con doppio slash “//”) Si può già adoperare tale comportamento con la direttiva from_future_import division Valori booleani: sono pari a False il valore 0, None e le sequenze vuote (come: '' "" () [] {} ): tutto il resto è True La valutazione delle espressioni booleane è intelligente (short boolean) per cui si ferma appena possibile: if (a<>0) and (3/a >1): non dà errore nel caso a sia pari a zero Sono possibili costrutti per range: if x < 5 or 10 < x < 20 :
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
print “Il valore è OK.”
· none equivale al null del C (però non è un tipo numerico) · Valori booleani: sono pari a False il valore 0, None e le sequenze vuote (come: '' "" () [] {} ): tutto il resto è True
Messaggi di errore (interpretazione)
· definizione multipla di un parametro : in realtà stai passando troppi parametri: uno riempito per “ordine”, l'altro ·
per assegnazione nominativa (parent=pippo) non key-arg dopo key arg: prova a mettere l'assegnazione nominativa (forse stai sbagliando l'ordine dei parametri)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Schema base di programma Ecco uno schema base per: 路 rendere il programma compatibile come script anche negli ambienti Linux 路 rendere possibile adoperare anche caratteri accentati 路 porre un commento descrittivo Esempio di applicazione minimale: #!/usr/bin/python # -*- Encoding:Latin1 -*""" Programma per ... """
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Iterazioni I blocchi (necessari per i comandi if, for, def, while) iniziano dalla riga successiva al ":" e terminano nella prima riga indentata quanto quella di partenza (o meno). Anche l'else è subito seguito dai ":". Il comando continue salta il solo ciclo in corso e riprende daccapo dalla iterazione successiva. Invece 'break' interrompe tutto il ciclo attuale SALTANDO anche le clausole else: (sia dell'if che del while), cosa utile per gestire la fine di iterazioni per errore e normali. Il comando print separa i parametri con virgole ed aggiunge CR a meno che l'ultimo parametro preceduto da virgola non sia vuoto print a,b, Sono presenti i seguenti operatori per ripetere segmenti di codice:
· Ciclo for · while · if
Ciclo For Il ciclo for itera gli elementi di una sequenza [stringhe, lettere di una stringa, dizionari, tuple, liste...]: ciò lo rende ben diverso (e più potente) rispetto al classico Basic. for Variabile in Sequenza: Blocco_di_istruzioni_da_eseguire_in_corso else: Blocco_di_istruzioni_finali for Q in ["a","b","c","d"]: print Q else: print ‘Ciclo terminato!'
# Essendo una lista, si usano le parentesi quadre
Output: –> a b c d Ciclo terminato Notare il comando else che viene eseguito al termine del ciclo, a meno che non sia stato usato il comando break L'elasticità del comando è dato dal fatto di poter lavorare su sequenze/liste: Per simulare il classico ciclo for di altri linguaggi si adopera il comando range() che costruisce una lista numerica: range (inizio, fine, passo) Al solito, è escluso l'ultimo elemento del valore fine. print ( range(1,5,1) ) –> [1,2,3,4] L'unico parametro obbligatorio è quello di fine (per default inizio=0, passo=1). La variante xrange() risparmia memoria non creando contemporaneamente tutti gli elementi (ad esempio xrange(1000) non crea 1000 elementi, ma permette comunque di iterare nella sequenza). In Python 3.0 diverrà default per range il comportamento “alla xrange()”
Notazioni varie La clausola else ha una sua utilità rispetto ad una semplice istruzione posta dopo il ciclo, in quanto può essere saltato interrompendo il ciclo con il comando break
Utilizzi particolari
· Lettura di un file di testo: FileTesto=open(”c:/esempio.txt”,”r”)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
· · ·
for SingolaLinea in FileTesto: print SingolaLinea Conteggio del n. di occorrenze delle singole parole di un testo (sfruttando un dizionario) for SingolaParola in Testo.split(): # Crea lista di singole parole di un testo Dizionario[SingolaParola] += 1 # Incrementa il valore corrispondente alla key SingolaParola List comprehension enumerate ()
If Per rendere più leggibile una sequenza di "else: if …:" può essere usato l'unico comando "elif:". Non si possono fare assegnazioni nelle condizioni (degli if, for,…): in compenso non è obbligatorio metterli tra parentesi. Esiste l'if ternario (o breve) come in altri linguaggi: a = '123' if b else '456' # Nel caso la condizione b sia vera, a=123, altrimenti sarà =456 Altro esempio: nome="Simone" risultato="furbo" if nome=="Simone" else "scemo" print risultato
While Perfino while ha un suo else:.
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Tastiera La lettura da tastiera avviene tramite:
· input () – e.g. pippo=input('Messaggio di richiesta') · raw_input () – e.g. pippo=raw_input('Messaggio di richiesta') che permette di non avere problemi con i caratteri speciali (che iniziano con slash /n,…) Dalla versione 3.0 sarà considerato default il raw_input () anche scrivendo semplicemente input ().
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Tipi di dati Variabili
· non vanno dichiarate, ma devono essere inizializzate prima di essere manipolate (non occorre dichiararne · · · ·
preventivamente il tipo come in C int n però occorre assegnare un valore n=2 prima di usarle richiamandone il valore (e.g. in elementi condizionali o calcoli matematici) Dispongono dell'auto-casting (cioè il tipo di variabile viene ricavato dal tipo di dato che viene assegnato) Sono possibili assegnazioni multiple: myvar, mystring = “variabile”, 5+2 ATTENZIONE: l'assegnazione di uguaglianza (a=b) tra due variabili, le rende un'unica entità (come se venissero unificati i rispettivi puntatori), per cui cambiando l'uno si modificherà automaticamente l'altra! Devi usare import copy e poi copy(variabile) Se ci sono più livelli, usa deepcopy L'assegnazione dentro una funzione rende la variabile automaticamente locale; per poter riferirsi ad una variabile globale, occorre precederne il nome con il comando global
Tipi di variabili In Python sono presenti i consueti tipi di dati: · interi · booleani: Valori booleani: sono pari a False il valore 0, None e le sequenze vuote (come: '' "" () [] {} ): tutto il resto è True · stringhe (immutabili una volte definite e con indice numerico che parte da zero) Inoltre sono presenti tipi particolari: · tuple: sequenze immutabili, ma rapide, comprese tra parentesi tonde (…) · liste: sequenze modificabili, lente, comprese tra parentesi quadrate [...] · dizionari: array associativi i cui elementi sono compresi tra parentesi graffe {…}
Nel caso di elementi indicizzati (array, slice,…): · il primo elemento si trova in posizione zero [0] · è possibile usare numeri negativi per contare dall'ultimo carattere [-1] –> ultimo carattere
Scope (variabili locali/globali) Questione apparentemente un po' confusa, ma che è necessario comprendere. In Python quando si passa come parametro una variabile, in realtà ne viene passato solo il valore (dunque solo una copia del suo valore, non puntatori alla variabile come in C). A ciò consegue che: · si lavorerà sempre con variabili locali (che cioè valgono solo all'interno della funzione/classe attuale), anche se l'inizializzazione del valore è avvenuta copiando una variabile globale · in genere è possibile usare (il valore delle) variabili globali, ma non modificarle; per poterle modificare, occorrerà darne un esplicito assenso con il comando global che sta a significare che (nel contesto attuale di funzione/classe) tutte le assegnazioni per quella variabile andranno fatte direttamente sulla variabile globale (e non su una copia locale come di default). Da sottolineare che non importa dove si trovi il comando global purchè sia all'interno della funzione/classe (Python è semi-compilato, quindi verrà letta tutta la funzione durante l'elaborazione), anche se per chiarezza sarebbe bene metterlo all'inizio. Dunque, a differenza di altri linguaggi, il comando global ha senso usarlo solo all'interno di una funzione (non al di fuori), perchè: o non definisce una variabile come globale in “assoluto” o ma dice solo che (all'interno della funzione/classe in cui si trova) i riferimenti a quella variabile andranno ricondotti alla omonima variabile globale o una variabile sarà globale definendola al di fuori delle funzioni/classi; la si potrà modificare come tale all'interno delle funzioni adoperando la dichiarazione global
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Ecco alcuni esempi: BAD=1
# Variabile globale perchè sta al di fuori di funzioni/classi
def foo(): global BAD BAD = 2
# le assegnazioni in tutta la funzione saranno riferite alla variabile globale
def bar(): BAD = 3 global BAD # stessa cosa (anche se il comando si trova dopo): tutte le assegnazioni (compresa quella della riga precedente) saranno riferite alla variabile globale def xyzzy(): BAD=”xyzzy”
# Assegnazione ad una variabile locale
def plugh(): print “BAD is”,BAD
# Richiama il valore della variabile locale (non serve global visto che non la modifica)
Quando Python incontra una variabile, ne cerca il nome/valore in quest'ordine: · localmente
· globalmente · tra i comandi built-in del linguaggio Comandi
· del (elemento) elimina una variabile (sarà necessario reinizializzarla per usarla), uno o più elementi (slice) di una lista o di un dizionario (tramite chiave)
Particolarità
· Sintassi valida per scambiare il valore di due variabili: x,y = y,x
Stringhe Sono immutabili e delimitate da apici singoli o doppi; quelli tripli identificano una stringa multilinea. Essendo immutabili, è possibile accedervi come fosse un array di caratteri in sola lettura. L'assegnazione StringaMia [2]='S' dà errore Di default tutte le stringhe vengono considerate con formattazione tipo linguaggio C, cioè con caratteri speciali slash (\n = CR) o con operatore % Sintassi: Stringa % valore oppure Stringa % (valore1, valore2) Ne consegue la necessità di usare ad esempio il doppio slash ove serve quello singolo (ad esempio nei nomi dei file: "C:\\autoexec.bat") Per evitare tale interpretazione (cioè casini con stringhe contenenti slash o percentuali) occorre anteporre una “r” prima delle virgolette (e.g. miaStringa = r“ciao\n simone” ). ATTENZIONE: anche con r"..." a precedere la stringa, NON è concesso di terminare la stringa con lo slash \ senza che venga interpretato come nel C --> casini! Al solito, nello slicing (MiaStringa [0:2]) l'indice parte da da zero e l'ultimo numero indica il primo carattere non compreso
Funzioni disponibili
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Nota che vanno applicate alla stringa stessa, e.g. pippo.replace("a", "B") (invece per conoscere la lunghezza, occorre usare la funzione len che non e' una proprietà di stringa e.g. len(s))
· len(stringa) riporta la lunghezza della stringa (nota: NON puoi usarla come fosse una proprietà) · split divide una stringa in base ad un separatore (opzionale il n. max di suddivisioni) string.split(s[, sep[, maxsplit]])
e.g. AltezzaElemento = linea.split('=') [1] # Ricavo il solo valore numerico, cioè il 2° elemento (nota che è comunque una str il risultato) della riga: Stripes = 94 "nomefile.ext".split(".") [0] --> riporta solo "nomefile"
· join fa l'opposto usando come “collante” un carattere separatore · str () converte in stringa (presente già in automatico in print) · find ed rfind ricercano una sottostringa (partendo da un estremo), string.find(s, sub[, start[, end]]) riporta -1 se non trova nulla, altrimenti il relativo indice
· replace(old, new[, count]) riporta una stringa in cui ciascuna ricorrente di una sottostringa è sostituita con un'altra (si può specificare per quante volte al max)
· strip (), lstrip () e rstrip() rimuovono gli spazi bianchi e caratteri bianchi,CR, LF; è possibile passare un parametro per · ·
far rimuovere solo cose specifiche (e.g. per togliere il newline da fin linea occorre passare rstrip("\n")) upper, lower cambiano il case della stringa; e.g. "ciao".upper() --> "CIAO" . In realtà puoi anche importare la libreria string ed usare string.upper(nome) (ma è solo più complicato) in è in realtà un operato generico, ma che permette e.g. di sapere se un dato carattere è contenuto in una stringa: e.g. print ":" in "sal:ve" --> True
Curioso l”operatore repr che riporta un output più brutto ma fedele al dato (e.g. il corrispondente raw di una stringa, dati tecnici sul modulo,…) Per ordinare alfabeticamente delle stringhe, sfrutta la funzione .sort() delle liste di stringhe. E' possibile applicare più metodi ad un oggetto mettendoli in file: e.g. print VariabileStringa.lower().rstrip()
DocStrings Sono stringhe di documentazione presenti nella prima riga di un oggetto (funzione, metodo,classe) allo scopo di documentarla. E' possibile poi accedervi con l'attributo “__doc__” della funzione stessa o con il comando help() Esempio: def foo(): “Documentazione di foo” print foo.__doc__ help(foo)
Dizionari Sono array associativi i cui elementi, compresi tra parentesi graffe {…}, sono coppie {chiave:valore,…}. Da notare che le chiavi sono immutabili e non ordinate (dunque non ha senso l'accesso con slicing). Ai dati si accede tramite le chiavi: x={”A”:1, “B”:5} print x ["A"] –> 1 (se non esiste la chiave, viene segnalato errore) Sono possibili conversioni in tuple, liste,… (sia delle chiavi che dei valori)
Metodi dei dizionari Poichè non è in realtà un elenco ordinato sequenzialmente, ma accessibile solo in base alle chiavi (uniche), non esiste nessun comando append, ma semplicemente per aggiungere un elemento basta fare un'assegnazione: se l'elemento non esiste, viene aggiunto, altrimenti viene aggiornato. dizionario [chiave]=valore · in o has_key () riportano 1 se la chiave specificata esiste · [chiave] recupera il valore corrispondente alla chiave specificata tra parentesi quadre [...], segnalando errore Created with the Freeware Edition of HelpNDoc: Free help authoring environment
· ·
· · ·
nel caso non esista x={”A”:1, “B”:5} print x ["A"] –> 1 get () recupera il valore corrispondente ad una chiave: specificabile un default nel caso non esista Il valore dell'insieme delle componenti si ottiene tramite: o items : tuple delle accoppiate chiave,valore o keys : liste di tutte le chiavi o values : liste di tutti i valori clear () cancella il dizionario copy () ne restituisce una copia update () permette l'unione con un altro dizionario
Notazioni varie
· Stampa del contenuto di un dizionario (chiavi e valori): for key in dict.keys(): print key,dict[key] · E' possibile adoperare un dizionario per rimpiazzare la mancanza di un case/switch di altri linguaggi: casi = {'a': funzione_per_a, ‘b': funzione_per_b, ‘c': funzione_per_c} # Dizionario che associa funzioni agli elementi di scelta casi[lettera]() # Si richiama un dato elemento accedendovi tramite la chiave di scelta · Curiosa la forma: {} ["X"]=2 che assegna ad un elemento (che ancora non esiste) avente chiave “X” il valore 2 (equivale cioè a {”X”:2} )
Liste Sono sequenze modificabili (anche eterogenee, ma lente) poste tra parentesi quadre [...]: X = [1,3, "ciao"]
Operazioni possibili
· slice, concatenazione, moltiplicazioni (un po' come le stringhe) · riscrittura di singoli elementi · · · · · ·
· ·
[5,3,1] [0] = 8 –> [8,3,1] sostituisce il primo elemento [0] della lista [5,3,1] con il valore “8” append () per aggiungere in fondo un elemento extend () per aggiungere in fondo un'intera lista insert () e pop () per mettere/togliere (& riportare) singoli elementi indicandone la posizione remove () per togliere la prima occorrenza di un certo valore reverse () per invertire la lista sort () per ordinarla; opzionalmente si può specificare il criterio di sorting (può essere anche una funzione!). E' in grado di ordinare anche serie di liste/tuple,confrontando dapprima il primo membro di ciascun elemento; in caso di parità, allora ne confronta i secondi membri….In pratica, se ciascun elemento tuplato contiene (GiornoNumerico, Ora, Impegno), sort li ordinerà per giorno, poi per ora e quindi per impegno! in operatore per verificare se esiste un dato valore nella lista e.g. [if pippo in lista: ... index () rispetto a in riporta anche l'indice del primo dato trovato; se non lo trova, dà errore (vedi qui per dettagli http://effbot.org/zone/python-list.htm )
List comprehension Il termine significa descrizione di lista e consente di mappare/trasformare una lista in un'altra applicandovi una funzione. Poichè il risultato è una lista, occorre specificarlo all'interno di parentesi quadre. Ecco un esempio:
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
partenza= [1, 9, 8, 4] risultato = [temp * 2 for temp in partenza] print (risultato) [2, 18, 16, 8] Per capirne il funziomento, è meglio leggerlo da destra a sinistra ( <-- ): viene presa la lista partenza , ciascun suo elemento è attribuito temporaneamente alla variabile temp su cui viene svolta un'operazione (*2): verrà così creata una lista di risultati che finirà in risultato. La sintassi può essere ulteriormente complicata/raffinata aggiungendo in fondo l'operatore if che fungerà da filtro (in base al valore vero/falso dell'espressione): il valore verrà dato in pasto al resto della "mappatura" solo se l'espressione if sarà vera. Ecco un altro esempio: partenza= [1, 9, 8, 4] risultato = [temp * 2 for temp in partenza if temp >5] print (risultato) [18, 16] Cioè ha considerato solo i due valori >5
=
Tuple Sequenza immutabile, ma di rapido accesso, comprese tra parentesi tonde ( ): x=(1,2,3) (in realtà se non ci sono ambiguità, come in questo caso, non sono indispensabili le parentesi). Per creare però una tupla con 1 singolo elemento, occorre specificare anche una virgola e.g. tuplaMia=('a',) altrimenti la scambierebbe per una stringa tra parentesi E' possibile anche il processo inverso di “spacchettizzazione”: a,b,c = x # assegna a=1, b=2, c=3 Nota però che non è possibile aggiungere o eliminare elementi dopo la iniziale dichiarazione.
Operazioni
· [n] accesso ad un singolo elemento (con indice che parte da zero): · · · · · · ·
print x [0] –> 1 S[I:J] Slice da I incluso a J escluso X in S Cerca X nella sequenza S (non vi è però nessuna funzione che riporti la posizione [è un limite delle tuple in sè]) X not in S Inverso del precedente S + T Concatezione generica di sequenze S * N Iterazione di S per N volte len(S) Lunghezza della sequenza min(S), max(S) Minino e massimo di S
ATTENZIONE: se dichiari un dizionario con delle tuple come valori, nel caso la tupla abbia 1 solo valore, essa va indicata dal valore seguito da una virgola isolata (”ciao”,) altrimenti il valore “ciao” verrebbe preso per stringa ed un eventuale ciclo for occorrerebbe lungo ogni singola lettera della parola c,i,a,o.
Conversioni · ord (char) riporta il codice ASCII del carattere char · int (stringa) converte una stringa in intero Created with the Freeware Edition of HelpNDoc: Free help authoring environment
· float (stringa) converte una strina in numero float · repr (numero) e str(numero) convertono un numero in stringa (forse più in generale riporta una versione stampabile di ·
quanto passato) eval () non chiarissimo, riporta anche il tipo di dato forse
Float Accenno solo che per limitazioni intrinseche al modo con cui i computer memorizzano i numeri in virgola mobile, talora con n. di cifre in teoria infinito, ci si scontra con apparenti bizzarrie del tipo: >>> a=0.1 >>>a 0.10000000000000001 Attenzione quindi a fare confronti tra numeri reali: per cavarne le gambe, parrà assurdo, ma conviene prima convertirli in stringhe con str(n_float) , perchè in questo modo non vi saranno decimali "invisibili"; la funzione print () inganna (se si fa debug) perchè applica automaticamente la funzione str() . Solo da prompt (senza usare print(), ma digitando direttamente il nome della variabile), ti accorgeresti dell'inganno. Con print() mi facevo stampare i 2 numeri che in apparenza erano identici, ma il confronto tra essi dava disuguaglianza; messi entrambi in str() , ecco che è venuto fuori il risultato corretto!
Boolean Valori booleani: sono pari a False il valore 0, None e le sequenze vuote (come: '' "" () [] {} ) Tutto il resto è True
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Namespaces Glossario · Namespace: spazio di nomi, contenente elementi detti "attributi"; agli attributi di un namespace si accede con la sintassi namespace.attributo · Modulo: namespace che contiene funzioni e altri elementi, letto da un file. · Classe: una funzione in grado di generare istanze (costruttore). · Istanza: namespace che contiene funzioni dette metodi; l'istanza differisce dal modulo per il fatto che viene creata dinamicamente (mentre i moduli sono definiti con dei file) e che gli attributi sono indipendenti per ogni istanza, anche se l'istanza viene creata dallo stesso costruttore. · Metodo: funzione appartenente ad una classe, che solitamente modifica le variabili dell'istanza a cui appartiene (in altre parole cambia lo stato dell'oggetto). Dunque i moduli e le istanze delle classi sono esempi di namespaces. Quelli di "serie" (comandi print, dir,…) appartengono al namespace "__builtins__", ma nella pratica non occorre specificarlo. Per gli altri namespace, un modo per evitare di scrivere continuamente il nome del namespace è il comando: from namespace import attributo (ma c'è il rischio di "collisioni" di nomi) Una variabile locale dura il tempo del metodo che l'ha creata e.g. btn1 = wx.Button (...) Una variabile di istanza è valida quanto la durata dell'istanza che contiene il widget e.g. self.btn1 = wx.Button (...) Le variabili globali sono sconsigliate (con l'eccezione della classica: MyApp = wx.App() che sta al di fuori di definizioni di classi)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Moduli Sono file che contengono funzioni e/o altri comandi: si importano in toto con il comando 'import'. (e.g. import mialibreria ) oppure se ne possono importare solo specifiche funzioni con: from mialibreria import funzionemigliore
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Classi Per creare una classe scriviamo: class NomeDellaClasse : se è una “classe madre”(cioè non deriva da altre classi) class NomeDellaClasse(NomeClasseMadre): se è una “classe figlia” dopo la dichiarazione del nome della classe, inizializzaremo le variabili (i dati membro) che utilizzaremo nella classe, ed infine sotto i metodi (funzioni) della classe.con una struttura di questo tipo: class NomeClasse: {variabili} {metodi} oppure class NomeClasse(ClasseMadre): {variabili} {metodi} Anche creandolo vuoto, è possibile usarlo x=pippo() #creata un'istanza di pippo E soprattutto, accedere ad una proprietà inesistente dà errore (print x.proprieta1), a meno che io non la aggiunga "al volo" facendo una qualche attribuzione: x.proprieta1 = "ciao" che creerà una nuova proprietà ora accessibile print x.proprieta1 ->>> ciao Le istanze delle classi si comportano in maniera più sofisticata dei moduli in quanto mantiene uno stato (spazio) separato per ogni istanza, per cui da una stessa classe si possono creare più istanze, ciascuna con variabili indipendenti. In altre parole: un modulo ha le sue proprietà e metodi, ma così pure anche le istanze che possono però essere presenti in più copie (a partire da una medesima classe) senza avere problemi di interferenza tra loro; in pratica sono moduli più sofisticati, più vicini a dei template/modelli riusabili in più copie contemporanemante. Le variabili/metodi/funzioni avranno ciascuna validità indipendente nel proprio spazio specifico (namespace) di creazione. Ancora, rispetto ai moduli le classi dispongono di un metodo di inizializzazione per le varie istanze (__init__) e sono anche sottoponibili alla ereditarietà. Le classi e le funzioni sono contenute in moduli (da importare con "import" per renderle accessibili). Moduli: - Classi - Istanza = modulo + namespace proprio - Funzioni La classe è in pratica un costruttore (creatore) di istanze. L'oggetto istanza si comporta come un modulo, cioè come contenitore di funzioni [in termini rigorosi, significa che con la classe si possono creare istanze le quali sono oggetti con propri metodi e proprietà N.d.S. Come dice il libro, la classe sta ad un 'tipo' come l'oggetto ad una variabile di quel tipo; l'oggetto è un istanza ottenuta da un certo tipo di classe]. Il metodo __init__ è un'ottima occasione per creare delle proprietà dell'oggetto (basta fare una qualsiasi dichiarazione, magari sfruttando i parametri passati al momento della creazione della istanza) cui potranno fare riferimento anche gli altri metodi della classe in seguito. Ripeto che le classi (versioni più raffinate dei moduli) sono contenute in dei moduli (che sono file) e dunque per accedervi occorre dapprima importarne il relativo modulo. import httplib # (importa il modulo che gestisce il web) All'interno è contenuta la classe HTTP cui accedo indicando httplib.HTTP Più precisamente, per creare una istanza "X" di detta classe (contenuta nel modulo httplib) scrivo: X = httplib.HTTP (parametri vari) Nome istanza = accesso al modulo.accesso alla classe (parametri specifici) Se occorre fare delle inizializzazioni ogni volta che viene creata un'istanza, basta metterle in una funzione chiamata obbligatoriamente __init__ Nelle istanze i metodi (funzioni) sono particolari in quanto sanno con che tipo di oggetto hanno a che fare. Attenzione: mentre in vari altri linguaggi OOP (tipo il C++) l'oggetto corrente cui fanno riferimento è implicito, invece in Python l'oggetto corrente viene passato come primo parametro della chiamata al metodo: per questo OGNI definizione di metodo all'interno di una classe ha almeno 1 parametro (o il primo) che convenzionalmente riceve il nome 'self'). Per convenzione il primo parametro di un metodo viene chiamato self (non c'è niente di speciale in questo nome ma non seguire questa convenzione può compromettere la leggibilità del vostro listato ad altri programmatori Python).
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
In pratica, ogni volta che viene invocato un metodo per un certo oggetto istanza di una classe, l'implementazione del metodo nella classe riceve sempre come primo parametro l'oggetto su cui operare (una roba del genere doveva accadere con Delphi) ed a seguire gli eventuali parametri: def __init__(self, data, next=None): Dunque viene passato l'istanza/oggetto di riferimento e poi due parametri che saranno specificati al monento della prima creazione dell'istanza (in realtà, notando la sintassi del secondo, si vede che è opzionale e, nel caso mancasse, assumerà il valore di default None). In altre parole, il metodo __init__ è quello che viene chiamato quando si crea l'istanza la prima volta e.g. con x =modulo.classe (parametri) ed i parametri specificati saranno passati proprio al metodo __init__ (naturalmente a seguire il self specificante l'oggetto/istanza in questione). Se tali parametri potranno essere utili ad altri metodi, sarà bene convertirli in proprietà dell'oggetto self.dataperfuturo = data. Non ci sono modi per accedere direttamente ai campi di un oggetto: occorre usare sempre il prefisso self Per quanto questa cosa possa apparire noiosa, in pratica questo migliora la leggibilità e evita ambiguità con le variabili locali. In pratica, nell'implementazione dei metodi occorre sempre anteporre self. per poter lavorare sulle proprietà dell'oggetto. class List: # definizione di una classe chiamata List def __init__(self, data, next=None): #inizializzazione comune: sfrutta 3 parametri: il primo è il nome dell'oggetto/istanza con cui si ha a che fare, e poi 2 parametri (di cui l'ultimo facoltativo) self.data=data # crea una proprietà '.data' dell'oggetto, attribuendole il valore di uno dei parametri self.next=next # stessa cosa con l'altro parametro Non c'è distinzione tra procedure e funzioni (si differenzino solo per il fatto che le seconde presentano il comando return )
Ereditarietà Serve per riutilizzare ed espandere classi già esistenti. Per creare una classe derivata che eredita proprietà e metodi di un''altra, al momento della definizione della classe basta specificare tra parentesi da chi deve ereditare, anche più di una classe (eredità multipla). Nella __init__ della classe derivata devo però richiamare le __init__ di tutte le classi base (da cui ho ereditato) Esempio: class pippo (animali, cartoni): #definisce una nuova classe pippo che avrà le proprietà e metodi (solo pubblici naturalmente) dalle classi preesistenti animali e cartoni. Nella classe derivata (pippo) posso anche ridefinire metodi ereditati, cioè riusarne il nome per far fare loro qualcos''altro. In caso di sovrapposizioni tra le eredità, conterà quella meno profonda nella gerarchia (suppongo sia la definizione più recente). Per accedere ai metodi della classe base (operazione necessaria per sfruttare il codice preesistente) si deve far riferimento esplicitamente al metodo chiamandolo con il nome della classe e passando self come parametro. Esempio: import math class Punto2D: # definisco una nuova classe Punto2D def __init__(self, x, y): # inizializzazione di Punto2D self.x = x self.y = y def dist(self): return math.sqrt(self.x **2 + self.y **2) class Punto3D(Punto2D): # definisco una nuova classe Punto3D che discende/eredita da Punto2D def __init__(self, x, y, z): # Inizializzazione di Punto3D Punto2D.__init__(self, x, y) # Sfrutto/richiamo l'inizializzazione di Punto2D self.z = z def dist(self): #Ridefinisco il metodo Dist con uno nuovo return math.sqrt(Punto2D.dist(self)**2 + self.z**2) Accenno solo il fatto che in Python è possibile l'overloading, e.g. ridefinire gli operatori + * … ridefinendo i
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
metodi __sum__ __mul__ â&#x20AC;Ś Ponendo una variabile tra il def di una funzione ed il successivo __init__ , si dichiarerĂ una variabile condivisa da tutte le istanze di quella classe (variabile di classe): una sua modifica in 1 istanza ne determina il cambiamento anche per tutte le altre
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Funzioni Le funzioni accettano variabili come parametri (anche con valori di default) e restituiscono qualsiasi tipo di oggetto. def funzione (arg1, arg2=ValoreDefault): In python i parametri passati alle funzioni sono sempre trasferiti per valore. Si può far riportare un valore tramite l'istruzione return Curiosa questa espressione: >>> def foo(x, y, z=42, k=12): print x, y, z, k ... >>> foo(5, 3, k=9) 5 3 42 9 In pratica ha passato 3 parametri, lasciando come default il terzo anzichÊ il quarto (forse pechè ha specificato il nome della variabile da assegnare con l'ultimo valore) Particolare il comando next() che salva e poi fa ripartire una funzione da dove si era fermata in precedenza >>> def f(a, b): while 1: (a, b) = (a-b, a+b) yield (a,b) >>> x = f(1,2) >>> x.next() (-1, 3) >>> x.next() (-4, 2) >>> x.next() (-6, -2) def area(width,height): return width*height
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Eccezioni Consistono nella gestione degli errori. In pratica si sottopone a vigilanza un blocco con il comando try: (i ":" servono per il blocco a seguire) Nel caso insorga un errore nel blocco, il tipo di errore verrà confrontato con la tipologia prevista dai successivi comandi except TipoDiErrore: (i ":" indicano che a seguire c''è il blocco di istruzioni che sarà eseguito in caso di corrispondenza). Un comando except può gestire più di 1 errore contemporaneamente: except (NameError, TypeError, ValueError):... È possibile memorizzare l'eccezione in una variabile except (NameError, ValueError), e: print e La clausola else: che specifica del codice da eseguire nel caso non si verifichino errori. La clausola finally: specifica un blocco da eseguire in ogni caso (con errore o senza) Per far le prove e determinare un errore, si usa il comando raise, utile anche per far emergere l''errore in un except dopo aver magari stampato qualcosa prima
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Files I file vengono gestiti in modo molto semplice e simile al C · open(nomefile[, modo]) apre nomefile in modalità modo (“r” è il valore di default, vedi tabella più avanti) e ritorna un oggetto di tipo file e,g, FileTesto=open("c:/vcalc.txt","r") for SingolaLinea in FileTesto: print SingolaLinea · close() chiude il file (richiamato automaticamente dall'interprete). Comunque si usa filetesto.close() · read([n]) ritorna “n” byte dal file (se “n” è omesso legge tutto il file) · readline() ritorna una riga · readlines() riporta una lista con le righe rimanenti nel file · write(str) scrive str nel file, e.g. f.write('linea di testo\n') Notare il \n per aggiungere un CR · writelines(list) scrive tutti gli elementi di “list” su file · flush() scrive su disco i dati presenti in eventuali buffer · seek(offset[, posiz]) muove di offset byte rispetto a posiz. I valori di posiz sono: o 0: dall'inizio del file (valore di default) o 1: dalla posizione corrente o 2: dalla fine del file (“offset” è normalmente negativo) · tell() riporta la posizione corrente
· truncate([n]) tronca il file a non più di n byte (default è la posizione corrente) Elenco dei modi di apertura di un file Mode s
De scription
r
Opens a file for re adin g on ly. T he file pointer is placed at the beginning of the file. T his is the default mode.
rb
Opens a file for reading only in binary format. T he file pointer is placed at the beginning of the file. T his is the default mode.
r+
Opens a file for both reading and writing. T he file pointer will be at the beginning of the file.
rb+
Opens a file for both reading and writing in binary format. T he file pointer will be at the beginning of the file.
w
O pe n s a file for writin g on ly. O ve rwrite s th e file if th e file e xists. If th e file doe s n ot e xist, cre ate s a n e w file for writin g.
wb
Opens a file for writing only in bin ary form at. Overwrites the file if the file exists. If the file does not exist, creates a new file for writing.
w+
Opens a file for both writing and reading. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing.
wb+
Opens a file for both writing and reading in binary format. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing.
a
Opens a file for appe n din g. T he file pointer is at the end of the file if the file exists. T hat is, the file is in the append mode. If the file does not exist, it creates a new file for writing.
ab
Opens a file for appending in binary format. T he file pointer is at the end of the file if the file exists. T hat is, the file is in the append mode. If the file does not exist, it creates a new file for writing.
a+
Opens a file for both appending and reading. T he file pointer is at the end of the file if the file exists. T he file opens in the append mode. If the file does not exist, it creates a new file for reading and writing.
ab+
Opens a file for both appending and reading in binary format. T he file pointer is at the end of the file if the file exists. T he file opens in the append mode. If the file does not exist, it creates a new file for reading and writing.
Modulo os (pg. 240 "Python in a nutshell") Fornisce gli strumenti per lavorare su directory e file. Ecco un elenco delle funzioni disponibili per gestire directory, file o entrambi; spesso esistono comandi "doppi" Created with the Freeware Edition of HelpNDoc: Free help authoring environment
(con il nome più lungo) in grado di lavorare su più elementi in una volta. Il percorso e nome dell'applicazione in esecuzione è contenuta nella proprietà argv del modulo sys e.g. print (sys.argv) Anche i parametri di linea sono passati con la medesima variabile (suppongo) · Directory: o os.getcwd () e os.chdir (percorso) riportano/cambiano la dir di lavoro attuale o os.mkdir (percorso) crea una nuova directory con l'ultimo componente di percorso; dà errore se parte del percorso precedente non esiste (oltre al caso in cui esista già o non riesca a crearla) o os.makedirs (percorso) come sopra, ma se necessario crea anche più di una dir n*el percorso indicato o os.rmdir (percorso) elimina la directory vuota specificata (errore se non è vuota) o os.removedirs (percorso) elimina le directory vuote presenti nel percorso specificato o os.listdir (percorso) riporta una lista contenente tutte le subdir e file di percorso (IL RISULTATO COMPRENDE SOLO I NOMI, SENZA PATH COMPLETO) Bada che puoi costruire filtri con le funzionalità di Python: e.g. nel seguente esempio che è l'ultima riga di una fne viene riportata una lista filtrata return [templist.lower() for templist in os.listdir(PathPlaylists) if templist [-4:]==".m3u"] # ricavo la lista dei file .m3u e ne converto il nome in minuscolo Nota: esiste una funzione omonima nel modulo dircache (dircache.listdir(percorso)) che in più: § riporta una lista ordinata § utilizza una cache per cui ad una successiva rilettura risulta più veloce (ma comunque riconosce automaticamente cambiamenti nella dir) · Files: o os.path.exists (file o dir) riporta True se esiste il file specificato; per essere sicuri che si riferisca ad un file, controllare con isfile() o remove (file) elimina il file specificato · Directory e files: o Esistenza dir: vedi os.path.exists() sopra nella sezione files o rename (vecchio_path, nuovo_path) rinomina il file/dir vecchio_path con nuovo_path o renames (vecchio_path, nuovo_path) come sopra, ma crea ed elimina le dir necessarie/vuote presenti nei due path (in pratica, questo comando è costituito dalla successione dei comandi makedirs e removedirs o stat (percorso) riporta alcuni attributi del file/dir di percorso. Agli attributi si accede come fosse un array contenente i vari attributi in 10 elementi (da 0 a 9); si può usare direttamente l'indice numerico oppure delle proprietà (con nomi più comprensibili). Esempio: sono equivalenti tra loro queste forme: print os.stat(percorso) [6] ---> print os.stat(percorso).st_size stampa la grandezza inbyte del file/subdir print os.stat(percorso) [8] ---> print os.stat(percorso).st_mtime stampa la data/ora di ultima modifica del file/subdir § st_size : dimensioni in byte § ST_ATIME: ora dell'ultimo accesso § st_mtime: ora dell'ultima modifica § ST_CTIME: variabile secondo il S.O.: in Windows rappresenta la data di creazione
o walk (percorso) riporta una lista di tuple (immutabili tra parenetesi tonde) ciascuna contenente il path della dir attuale, nonchè la lista dei file e delle subdir presenti nella dir attuale. In altre parole, riporta ricorsivamente il contenuto di ciascuna directory (e relative sottodirectory) presenti nel path specificato. L'elenco in genere viene "percorso" in ordine topdown, dando modo di poter cambiare i singoli elementi in corso d'opera (se invece si passa il parametro topdown=false l'intera dir viene letta tutta all'inizio per poter procedere in ordine inverso. Nota: esiste una funzione walk di "serie" (al di fuori di queto modulo), ma è complicata ed obsoleta PER COMPITI PIU' SEMPLICI (non ricorsvivi) puoi usare listdir for dir_, subdirs, files in os.walk (base): ^. ^. ^..............................................è l'elenco dei file contenuti nell' attuale dir_ \ \......................................... è l'elenco delle cartelle contenute nell' attuale dir_ \......................................... è la dir che si sta scansionando in questo momento
Nota: · Python accetta come formato dei path queli di Linux ed altri S.O.. Poichè però il formato windows ("\" per dividere directory) si incasina con l'interpretazione delle stringhe tipo linguaggio C, è bene adoperare
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
· ·
sempre il formato Linux con "/" (peraltro il più portabile). e.g. o=open("c:/Ambulatorio/MomPython"+cognomenome+'.ini.txt',"w") è molto ad oggetti l'uso: o.close() oppure o.write(....) (e non close (o) come faceva delphi!) per conoscere la dir attuale, basta usare il comando dirAttuale=os.getcwd() che credo in genere coincida con quello dell'applicazione stessa
Wildcard La cosa migliore è usare la libreria glob, mettendo glob.iglob(filename) al posto di filename semplice (peraltro non è obbligatorio specificare una wildcard, accetta anche un nome di file normale, Attenzione che però forse riporta slash alla windows I consueti comandi dei file NON accettano espressioni con wildcard, ma si può facilmente aggirare il problema con la libreria glob che riporta una lista di file in base alla wildcard specificata. glob contiene due metodi: l'omonimo glob (che crea una lista unica all'inizio, cosa lenta se ci sono tanti file) ed iglob che invece li crea man mano, risultando più snello e rapido se ci sono molti risultati: Esempio: for filename in glob.glob('new*.mxd') : # SCONSIGLIATO GLOB SE VI SONO TANTI RISULTATI: MEGLIO glob.iglob ('new*.mxd') os.remove( filename ) Ma sembra funzionare anche: import os fileList = os.listdir(os.getcwd()) for fn in fileList: os.remove(os.path.join(os.getcwd(), fn)) Ancora: Note that I'm using iglob (added in Python 2.5) which creates a generator, so it does not load the entire list of files in memory first (which is what glob does). from glob import iglob from shutil import copy from os.path import join def copy_files(src_glob, dst_folder): for fname in iglob(src_glob): copy(fname, join(dst_folder, fname)) if __name__=='__main__': copy_files("123*.xml", "out_folder") glob.glob is slow is there are a lot of results because it returns one huge list of all the results in a "big bang" approach. If there are a lot of results this will use a lot of memory and take a long time. Use glob.iglob instead, as suggested by a previous poster. iglob constructs and returns one iterator object that can be used to loop over the results, without ever having them all in memory at the same time. It's much more efficient if there are a lot of matches. Sotto-modulo os.path Comprende funzioni per elaborare i path · Costituenti del path: o basename (percorso) riporta solo filename.ext o dirname (percorso) riporta il solo path (senza il filename e senza il "\" finale) o split (percorso) riporta, a partire da percorso, coppie di stringhe date dall'ultimo elemento e dal blocco di tutti quelli precedenti. La stringa dell'ultimo elemento non conterrà separatori. Esempio: os.path.split ('a/b/c/d) ---> ('a/b/c','d') o splitext (percorso) riporta, a partire da percorso, una coppia di stringhe date dall'estensione ed il blocco di tutti quelli precedenti. Esempio: os.path.splitext ('a.a/b.c.d') ---> ('a.a/b.c','.d') NOTA CHE C'è ANCHE IL PUNTO NELL'ESTENSIONE RIPORTATA o join (percorso1, percorso2,... ) riporta una stringa path congiungendo le stringhe parametro con il separatore di path opportuno per il S.O.
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
o normpath (percorso) riporta una stringa path corretta per taluni aspetti (rimozione di doppi slash, utilizzo di separatori adatti al S.O.)
· Tipologie di elementi o isfile (percorso) verifica se percorso sia un file o isdir (percorso) verifica se percorso sia una dir · exists (percorso) verifica l'esistenza di un file/directory · expandvars (percorso) elabora la stringa percorso in modo da sostituire eventuali valori $nome o ${nome} con corrispondenti variabili dell'environment. Esempio: print os.path.expandvars ('$HOME/directory1') Sotto-modulo os.filecmp Comprende funzioni per confrontare file e directory. Sotto-modulo os.shutil Comprende funzioni avanzate per copiare (anche overwrite) o muovere file/directory. · shutil.copyfile(src, dst) permette la copia di un FILE specificandone il nome completo come destinazione (se invece si vuole specificare solo la directory di target, allora bisogna adoperare shutil.copy(src, dst) Reference: http://docs.python.org/library/shutil.html
· shutil.copytree(src, dst[, symlinks=False[, ignore=None]])
Recursively copy an entire directory tree rooted at src. The destination directory, named by dst, must not already exist; it will be created as well as missing parent directories. Permissions and times of directories are copied with copystat(), individual files are copied using copy2(). If symlinks is true, symbolic links in the source tree are represented as symbolic links in the new tree; if false or omitted, the contents of the linked files are copied to the new tree.
If ignore is given, it must be a callable that will receive as its arguments the directory being visited by copytree(), and a list of its contents, as returned by os.listdir(). Since copytree() is called recursively, the ignore callable will be called once for each directory that is copied. The callable must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process. ignore_patterns() can be used to create such a callable that ignores names based on glob-style patterns. Eseguire programmi esterni In teoria esistono varie funzioni del modulo os, oltre a os.system, os.popen, spawn... Sono comunque troppo di basso livello: meglio adoperare il modulo subprocess che astraggono il tutto ad un livello più elevato per l'utente (senza utilizzare direttamente os.system, os.spawn*, os.popen, popen2.* o commands.* i quali hanno un livello di complessità di gestione sicuramente più elevato). >>> import subprocess >>> subprocess.Popen (["notepad.exe","c:/config.xml"]) ...lancia notepad.exe con il parametro c:\config.xml, disimpegnando la shell. Nota che i parametri (compreso il nome-path dell'exe) sono una lista subprocess.call(*popenargs, **kwargs) Chiama un programma e ne aspetta la chiusura subprocess.check_output(*popenargs, **kwargs)
Run command with arguments and return its output as a byte string.
Esempio di sostituzione dell'uso di os. con subprocess. sts = os.system("mycmd" + " myarg") ==> p = Popen("mycmd" + " myarg", shell=True) sts = os.waitpid(p.pid, 0)[1] REFERENCE= http://docs.python.org/library/subprocess.html Per dettagli, vedi http://docs.python.org/library/subprocess.html
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Gestione file.ini Per gestire i file .ini si può adoperare il modulo ConfigParser (in 3.0 diventa minuscolo, configparser: la conversione verrà effettuata in automatico da apposito tool). ( vedi: http://docs.python.org/library/configparser.html#RawConfigParser-objects) e http://docs.python.it/html/lib/module-ConfigParser.html in italiano ) Il formato prevede: · suddivisione in sezioni contenenti un'intestazione con il relativo nome tra parentesi quadre [sezione1] · all'interno, assegnazione di valori a variabili (chiamate Options nella libreria ConfigParser) variabile (tramite "=" o ":"): e.g. pippo:2 oppure pippo=2 · rimozione degli spazi iniziali dai valori · possibili valori che si estendono su più righe · commenti preceduti da ";" o "#" · possibilità di variabili interne al file (per dettagli, vedi http://www.python.org/doc/2.6.1/library/configparser.html?highlight=configparser#ConfigParser.ConfigParser ) · gestione di dizionari Sembra che la libreria funzioni così: · dapprima si crea il testo virtualmente (aggiungendo sezioni, valori,...) · solo alla fine si scrive il file con il testo fin lì creato Nel caso si voglia aggiornare solo qualche valore, occorre: · creare l'oggetto ConfigParser · leggere il file .ini originale con .read(filename) [altrimenti verrà perso tutto ciò che non viene modificato] · aggiornare i valori che si vuole (e.g. con set(...)) · scrivere il file import ConfigParser FileIni=ConfigParser.ConfigParser() # Creo un oggetto file parser .ini FileIni.read((NomeFileIni) # Leggo il contenuto attuale (per non perderlo) FileIni.set(Sezione,NomeVariabileOption,DatoDaScrivere ) # Aggiorno la data del file testo della Terapista with open(NomeFileIni, 'w') as configfile: # Scrivo il file operatori.ini (esempio copiato, il costrutto non è chiarissimo); se esiste, lo sovrascrivo FileIni.write(configfile) Metodi disponibili in ConfigParser: · Per ottenere i contenuti: o sections() : riporta la lista delle sezioni presenti (DEFAULT non viene riportata) o options(section): riporta la lista delle opzioni (variabili) presenti in una data sezione o items(section) riporta una lista di coppie (nome, valore) per ogni opzione (variabile) nella sezione section. o get(section, option): riporta il valore della variabile (option in section) specificata; esistono metodi che effettuano anche una conversione del valore: § getint(section, option) § getfloat(section, option) § getboolean(section, option) NOTA: se non viene trovata una sezione, controlla se hai caricaro il file con .read() · Per verificare l'esistenza di specifici elementi: o has_section(section) controlla se esiste una data sezione o has_option(section, option) controlla se esiste una certa variabile · Per modificare i contenuti: o add_section(section) aggiunge una certa sezione (errore DuplicateSectionError se esiste già) § remove_section(section) rimuove una sezione (se non esiste riporta false, altrimenti true) § remove_option(section) rimuove una opzione (variabile) o set(section, option, value): assegna all'opzione option il valore value (errore nel caso non esista la sezione o il valore non sia una stringa; in pratica crea una option e le assegna un valore)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
· Gestione files: o readfp(fp[,filename]): legge il file di configurazione dall'oggetto file fp o da filename o read(filenames): tenta di leggere ed analizzare una lista di nomi di file, restituendo l'elenco di quelli
o o
analizzati con successo; se viene passata una sola stringa, viene aperto tale file. Se un file elencato in filenames non può essere aperto, quel file verrà ignorato. In questo modo è possibile specificare una lista di possibili locazioni di file di configurazione (per esempio, la directory corrente, l'home directory dell'utente ed alcune directory di sistema) ed ogni file di configurazione presente nella lista verrà letto. Se non esiste nessuno dei file nominati, l'istanza di ConfigParser conterrà un insieme di dati vuoto. Un'applicazione che richiede che dei valori iniziali siano caricati da un file, dovrebbe caricare il file o i file richiesti usando readfp() prima di chiamare read() per ogni file facoltativo. write(filename): scrive il file write(filename): scrive il file di configurazione
Esempio: File "config.cfg" adoperato nell'esempio: [colori] # sezione colore_sfondo="#cecece" colore_testo="#000000" Programma: import ConfigParser cfg=ConfigParser.ConfigParser() cfg.read('config.cfg') cfg.sections() cfg.options('colori')
# # # # #
importa la libreria creo un oggetto derivato dalla classe ConfigParser leggo il file "config.cfg" --> riporta ['colori'] --> riporta ['colore_sfondo', 'colore_testo']
Esempio di scrittura: import ConfigParser config = ConfigParser.RawConfigParser() # When adding sections or items, add them in the reverse order of how you want them to be displayed in the actual file. # In addition, please note that using RawConfigParser's and the raw mode of ConfigParser's respective set functions, you can assign # non-string values to keys internally, but will receive an error when attempting to write to a file or when you get it in non-raw # mode. SafeConfigParser does not allow such assignments to take place. config.add_section('Section1') config.set('Section1', 'int', '15') config.set('Section1', 'bool', 'true') config.set('Section1', 'float', '3.1415') config.set('Section1', 'baz', 'fun') config.set('Section1', 'bar', 'Python') config.set('Section1', 'foo', '%(bar)s is %(baz)s!') # Writing our configuration file to 'example.cfg' with open('example.cfg', 'wb') as configfile: config.write(configfile) In caso di esigenze più avanzate, è disponibile un tool esterno più complesso: ConfigObj (scaricabile presso http://www.voidspace.org.uk/python/configobj.html )
Esempi files # Scrive un file. out_file = open("test.txt","w") out_file.write("This Text is going to out file\nLook at it and see\n") out_file.close() Created with the Freeware Edition of HelpNDoc: Free help authoring environment
# Legge un file. in_file = open("test.txt","r") text = in_file.read() in_file.close()
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Versione 3.0 Alcuni moduli sono stati: 路 Rinominati per rispettare lo stile PEP-8: nomi tutti minuscoli, brevi, opznionale l'uso dell'undersore (_). 路 Rimossi (perch猫 poco utilizzati o sostituiti da altri): o modulo dl sostituito da sctypes o modulo dircache scarsamente usato e facilmente implementabile o modulo ihooks in quanto non documentata ed usata solo da rexec (tolta dalla versione 2.3 per questioni di sicurezza) o modulo popen2 sostituito da subprocess e sets o modulo md5 e sha sostituite da hashlib矛
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Self Argomento ancora un po' oscuro per me Terminologia: Classe = una sorta di stampo con cui creare istanze (elementi funzionanti) (http://forum.ubuntu-it.org/index.php?action=printpage;topic=345819.0) Quando chiami una funzione di una classe, ci devi passare l'istanza stessa [cioè quello che hai derivato dalla classe], questo perchè è sull'istanza stessa che vengono apportate modifiche [cioè non devi operare con lo stampo {classe} ma su ciò che hai creato con lo stampo]. In sostanza, la funzione membro di una classe non è altro che una funzione comune, che ha come primo parametro un'istanza della classe [forse, quando si fa uso di una funzione di una classe {chiaramente non direttamente, in quanto la classe è solo uno stampo, ma creando un'istanza della classe stessa} non viene creata una copia della funzione apposta per l'istanza, ma semplicemente esiste sempre e comunque una sola ed unica funzione che però accetta come primo parametro l'istanza della classe che si gioverà dei risultati della funzione]. Facendo così a.prt() oppure A.prt(a) chiami la funzione prt della classe A e questi due modi sono equivalenti!! infatti nel primo caso l'istanza viene passata automatiacmente, nel secondo caso chiami una funzione di una classe (non chiami una funzione di un'istanza) passandoci l'istanza. è equivalente self è una variabile e va tradotta come "se stesso". questo "se stesso" non è riferito alla classe ma all'istanza della classe.
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Tips & tricks Per sapere qualcosa su un elemento · type (elemento) dice la tipologia dell'elemento · dir (elemento) mostra i metodi dell'elemento · help (elemento) mostra la documentazione relativa all'elemento · self.btn.GetParent() riporta il Parent di un elmento (in questo caso un pulsante) Almeno da Eric4 editor, è molto comodo usare lo stdout (con print()) per il debugging Per eseguire un file (o aprire un file con il programma associato) vedi la voce nella sezione Files . Parametri e path applicazione Il percorso e nome dell'applicazione in esecuzione è contenuta nella proprietà sys.argv del modulo sys Per conoscere il n. di parametri: len(sys.argv) Per ottenere il percorso+nome applicazione: sys.argv[0] Per ottenere il primo parametro: sys.argv[1] Esempio: if len(sys.argv)<2: # 1 parametro c'è sempre: è il path del programma stesso. Questa riga ctl che sia passato almeno 1 parametro print "ERRORE: devi passare almeno un parametro su linea di comando" sys.exit() # Interrompo lo script Parametro=sys.argv[1] Terminare applicazione sys.exit(codice_di_ritorno) Se codice_di_ritorno non è specificato, esso verrà considerato uguale a zero (tutto ok). Applicare più metodi contemporaneamente ad un oggetto E' possibile applicare più metodi ad un oggetto mettendoli in file: e.g. print VariabileStringa.lower().rstrip() Per stampare senza che venga messo il CR, metti una virgola dopo print e.g. print "Ciao",
PyScripter Per evitare che dia errori di moduli non trovbati a sproposito, è necessario importare i moduli esterni con l'ozione Import (sotto Run), ripetendola se cambia il sorgente delle librerie
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Tempo Per gestire il tempo (ora e data) dalla versione 2.3 esiste la libreria di sistema datetime (necessario import datetime). Per lavorare con data (date) e tempo (time) contemporaneamente, si usa la sua (omonima, ahimè) proprieta datetime (accetta i valori in formato "tuplato"). Se invece voglio lavorare con la sola data o la sola ora, uso rispettivamente la proprietà date oppure time (al posto di datetime). A seguire ad una delle tre proprietà sopra citate occorre fornire il valore (tupla di interi con ordine americano),cioè: · prima l'anno [a 4 cifre] · mese · giorno · ore · minuti · secondi · microsecondi · tzInfo per i fusi orari Per lavorarci si possono usare: · direttamente tali elementi · adoperare funzioni apposite, ad esemio: today() che riporta sia la data sia l'ora (dipenderà dalla proprietà cui è legato se verranno riportate/adoperate entrambe le informazioni) Esempi: >>> print datetime.datetime.today() # Stampa data ed ora correnti 2007-09-19 08:14:52.218000 >>> print datetime.date(2007,12, 20) 2007-12-20 Attenzione: non mettere zeri prima delle cifre, non sembra gradirlo (strano!): >>> ieri=datetime.date(2007,9,19) Traceback ( File "<interactive input>", line 1 ieri=datetime.date(2007,09,19) ^ SyntaxError: invalid token Invece accetta ieri=datetime.date(2007,9,19) Il tempo (data & ora) può essere convertito (bidirezionalmente) da e verso singoli numeri in 2 formati possibili: · Gregoriano per cui il giorno zero è 01/01/01 cui si accede con fromordinal() · Posix il 01/01/1970 ci si accede con fromtimestamp() o in date formattate con i metodi strftime Esempi: >>>print datetime.date.today() 2007-09-18 >>> print datetime.datetime.today() 2007-09-19 07:54:35.109000 >>> print datetime.datetime.date(datetime.datetime.today()) 2007-09-19 Spiegazione: stampo ciò che ottengo accedendo alla proprietà datetime della libreria datetime, di cui tengo la sola componente data (con date); come sorgente del dato gli fornisco la proprietà today() della proprietà datetime della libreria datetime (...che uccise il toro, che bevve l'acqua,....) Per lavorare sul calendario: Vi è la libreria calendar : import calendar
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
calendar.isleap(anno) # restituisce True se l'anno è bisestile. weekday(anno, mese, giorno) # restituisce il giorno della settimana (0 = lunedí, 1 = martedí... 6 = domenica). Si può lavorare con i tipi datetime anche con confronti booleani: >>> ieri=datetime.date(2007,9,19) >>> domani=datetime.date(2007,10,10) >>> print oggi > ieri True Formattazione data ed ora Esistono una serie di metodi basati su strf che usa una stringa "modello" (con %d, %h....) per effettuare una conversione (bidirezionale) tra il formato tuplato e delle stringhe di vario formato. I comandi sono: · strftime(format[, tupla stile gmtime]) converte la tupla in una stringa formattata # now.py import datetime ora = datetime.datetime.now() print "Inizio il lavoro alle ore "+ora.strftime("%H:%M il giorno %d/%m/%y") · strptime(formato, stringa) funzione inversa di strftime: data una stringa, restituisce una tupla in stile gmtime, leggendo i valori secondo il formato dato ATTENZIONE: forse è cambiato qualcosa nella 2.5; quanto segue è tratto dall'help ufficiale: strptime( date_string, format) [NOTA CHE L'ORDINE DEI PARAMETRI E' INVERTITO! Forse fa parte di Time e non Datetime library] Return a datetime corresponding to date_string, parsed according to format. This is equivalent to datetime(*(time.strptime(date_string, format)[0:6])). ValueError is raised if the date_string and format can't be parsed by time.strptime() or if it returns a value which isn't a time tuple. Esempio funzionante: >>> a="20/12/2006" >>> d=datetime.datetime.strptime(a,"%d/%m/%Y") >>> d datetime.datetime(2006, 12, 20, 0, 0) Specifiche della stringa di formattazione: · %a Nome del giorno abbreviato, secondo la locale corrente · %A Nome del giorno completo, secondo la locale corrente · %b Nome del mese abbreviato, secondo la locale corrente · %B Nome del mese completo, secondo la locale corrente · %c Data e ora rappresentati secondo la locale corrente · %d Giorno a due cifre (da 01 a 31) · %H Ora a due cifre su 24h (da 00 a 23) · %I Ora a due cifre su 12h (da 01 a 12) · %j Giorno dell'anno a 3 cifre (da 001 a 366) · %m Mese a due cifre (da 01 a 12) · %M Minuto a due cifre (da 00 a 59) · %p "AM" o "PM" · %S Secondi a due cifre (da 00 a 61) · %w Giorno della settimana (da 0 (lunedí) a 6) · %x Data abbreviata · %X Ora abbreviata · %y Anno a due cifre (da 00 a 99) · %Y Anno a quattro cifre
· %Z Nome del fuso orario · %% Il carattere '%' Ci sono anche funzioni utili come:
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
· il n.del giorno dell'anno · i nomi dei giorni/mesi (non so in quale lingua) Esempi: Per sapere quindi giorno sarà tra cinque giorni da oggi, basta fare date.today() + timedelta(5) Il risultato è un altro oggetto di tipo date, a cui possiamo poi magari chiedere il metodo ctime() o strftime(formatoData) per avere una forma stampabile. # Adding to or Subtracting from a Date # Use the rather nice datetime.timedelta objects now = datetime.date(2003, 8, 6) difference1 = datetime.timedelta(days=1) difference2 = datetime.timedelta(weeks=-2) print "One day in the future is:", now + difference1 #=> One day in the future is: 2003-08-07 print "Two weeks in the past is:", now + difference2 #=> Two weeks in the past is: 2003-07-23 orainizio = datetime.datetime.now() orafine = datetime.datetime.now() differenza=orafine-orainizio print "Inizio il lavoro alle ore "+ora.strftime("%H:%M il giorno %d/%m/%y") print "Termine del programma alle ore ", orafine.strftime("%H:%M il giorno %d/%m/%y") print "Sono stati necessari ", print differenza.seconds, # NON CAPISCO: SE USO seconds() (con le parentesi) mi dà errore INT non callable print " secondi" ATTENZIONE nel fare confronti con datetime le ore che possono risultare "nascoste" se ti limiti a lavorare con le date (magari i confronti faliiscono perchè sono diverse le ore); per convertire in data pura, usa la funzione datetime.datetime.date(xxx) che non è equivalente a datetime.date...! Se fai l'errore di cui sopra, ti dice che stai dando 1 solo parametro anzichè 3 (perchè forse il datetime.date si aspletta una tupla giorno,mese, anno) Classe timedelta : rappresenta un intervallo di tempo precisato da soli 3 interi: giorni, secondi e millisecondi. (proprietà accessibili come .days , . seconds e .milliseconds). Il metodo timedelta (days, seconds, microseconds, milliseconds, minutes, hours, weeks) riporta un oggetto con tali 3 interi. Con timedelta posso fare confronti con se stesso, interi e datetime. In WxPython le date sono gestite dal modulo wx.DateTime (nota che vi è il wx e che è diverso anche il case!) che funzionalmente sembra un parente stretto della classe di Python. Per ottenere la data, pui usare data.GetDay() (servono le parentesi, e data deve essere di tipo daytime); credo riporti un intero (se vuoi la stringa, usa str()) ATTENTO CHE IL RANGE DI MONTH E' DA 0 A 11 !!!!!!!! Forse per sospendere l'esecuzione (delay) per 1.5 secondi basta l'istruzione: time.sleep(1.5)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Compilatore Distribuzione di programmi Tramite la liberia (di serie) distutils (utility per la distribuzione) è possibile preparare pacchetti (archivi compressi) per l'installazione di programmi sorgenti Python (vedi http://www.python.org/doc/current/distutils/introduction.html#concepts-terminology ) Il concetto di fondo è creare un file setup.py che si occupa di tutto (in esso si farà uso appunto delle librerie distutils). Passandogli come parametro: · sdist --> preparazione del pacchetto zippato, e.g.> setup.py sdist · install --> installazione , e.g. scompattando l'archivio e dando il comando > setup.py install Un esempio molto scheletrico è il seguente: from distutils.core import setup setup(name='foo', programma foo.py version='1.0', py_modules=['foo'], )
# importo il metodo setup dalla libreria distutils.core # Richiamo tale metodo con i parametri necessari per impacchettare il
Creazione di un file .exe tramite cx_freeze E' possibile creare un eseguibile con questa libreria che, con programmi wx, ha funzionato al primo colpo. E' adoperabile in 3 modi: · usando il comando script cxfreeze · creandosi un semplice file di setup (chiamabile setup.py o come ci pare...), più facile di quello di py2exe · lavora direttamente con le classi di cxfreeze Esempio di file setup.py per far compilare 2 programmi WxPython (PalestraComm.py e CreaOperatoreIni.py): # Run the build process by running the command 'python setup.py build' # If everything works well you should find a subdirectory in the build # subdirectory that contains the files needed to run the application import sys from cx_Freeze import setup, Executable base = None if sys.platform == "win32": base = "Win32GUI" setup( name = "PalestraComm", version = "0.2.2", description = "Programma di comunicazione tra palestra e medici V", executables = [Executable("PalestraComm.py", base = base), Executable("CreaOperatoreIni.py")]) Reference= http://cx-freeze.sourceforge.net/cx_Freeze.html
Creazione di un file .exe tramite py2exe (consiglio invece di usare cx_freeze) E' possibile creare un eseguibile che permetta di eseguire un programma Python senza problemi di installazione. Non si tratta di una vera compilazione perchè vengono semplicemente appiccicate le librerie necessarie al file che verrà comunque interpretato. Il processo avviene tramite l'utility esterna py2Exe, scaricabile presso: http://www.py2exe.org/ E' possibile scaricarlo con installer che metterà la libreria in Pythonx.xx\LIb\site-packages\py2exe Questa estende il sistema di distribuzione di Python tramite file setup.py (in cui vi sarà anche l'import di py2exe ed i Created with the Freeware Edition of HelpNDoc: Free help authoring environment
dettagli per il suo funzionamento), introducendo un nuovo parametro (oltre a sdist e install ): py2exe , e.g. > setup.py py2exe Come file di setup.py conviene prendere quello fornito con py2exe e copiarlo nella directory del proprio programma. Esempio di setup.py: from distutils.core import setup import py2exe setup(console=['hello.py']) # dice di creare un'applicazione tipo console e che il modulo principale entry) è hello.py Per eseguirlo e creare il file .exe basterà dare:> setup.py py2exe Come risultato si avranno 2 directory: · build : cancellabile in quanto directory temporanea di lavoro durante la creazione del pacchetto (meglio cancellarla) · dist : in cui si troveranno l'eseguibile e le librerie; Problema di py2exe: le librerie Poichè l'interprete Python è creato con il Microsoft C, sarà necessario portarsi dietro le relative librerie (che per questioni di copyright Python non può copiare in automatico, anche se è facile che siano già presenti sul computer destinatario). A seconda della versione di Python, serviranno versioni diverse di tali librerie: · versioni 2.4/2.5 --> MSVCR71.dll · 2.6 e successive --> MSVCR90.dll nella versione 9.0.21022.8 (quella esatta usata per l'interprete Python) Devo dire che alla fine mi ha dato molti problemi: molto meglio cx_freeze
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Suoni Per suonare singoli suoni, occorre: 路 sotto Windows appoggiarsi alla libreria winsound 路 sotto Linux alla ossaudiodev in combinazione con la sound Esempio: import winsound soundfile = "c:/Windows/Media/chimes.wav" winsound.PlaySound(soundfile, winsound.SND_FILENAME|winsound.SND_ASYNC) Nel caso si vogliano funzioni pi霉 sofisticate, si pu貌 usare la libreria esterna pymedia (scaricabile da http://pymedia.org/ )
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Errori & problemi Almeno sotto Windows7, non sempre l'associazione dei file riesce perfettamente: se l'esecuzione di un file python (.py o pyw) non dà alcun risultato di output (non fa nulla), prova ad associare nuovamente l'estensione con la specifica funzione di W7 (non usare TotalCommander che non ci riesce in maniera corretta): · .py --> python.exe · .pyw --> pythonw.exe (non mostra la console)
· Se una riga diventa commento, attento a non usare il sistema "delphi" per specificare un carattere (#10), ma invece devi usare chr(10)
· Ctl sempre di richiamare i metodi specificando almeno le parentesi tonde vuote () : python non ti dà errore se non le ·
metti, ma non fa nulla! Se non ci capisci nulla, prova ad eseguire il comando da linea di comando DOS (negli editor spesso vi sono strani comportamenti ed incompatibilità: in PyScripter devi spesso importare i moduli dal menu Run)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Librerie esterne Ecco alcuni librerie utili: 路 PIL (Python Imaging Library): per gestire/elaborare immagini (ruotare, scrivere, filtrare, text to image,...) ( http://www.pythonware.com/products/pil/ ) 路 PyLast : permette di accedere al sito last.fm ed altri siti API compatibili con esso ( http://code.google.com/p/pylast/ ) 路 sqlite3: gestione database SqLite ( http://docs.python.org/library/sqlite3.html )
sqlite3 MEDIAMONKEY SQL VIEWER http://www.mediamonkey.com/forum/viewtopic.php?t=24841 http://docs.python.org/library/sqlite3.html#sqlite3-Connection-Objects -----------import os import sqlite3 # Find the mediamonkey database. conn = sqlite3.connect( os.path.join(os.environ['USERPROFILE'], 'Local Settings', 'Application Data', 'MediaMonkey', 'MM.DB') ) conn.row_factory = sqlite3.Row # provide named columns in results # Ask mediamonkey for its data. cursor = conn.cursor() # Get the total number of songs. cursor.execute("select count(*) as count from songs") track_estimate = cursor.fetchall()[0]['count'] > I wonder whether it's complaining about the "as count" part because > "count" is the name of a function, although you do say that the same > query works elsewhere. Hey, good catch. Thanks; I'll change that. (It wasn't the problem, but no doubt someday it could be.)
import sqlite3 # define IUNICODE collation function def iUnicodeCollate(s1, s2): return cmp(s1.lower(), s2.lower()) # connect to database conn = sqlite3.connect('MM.DB') # register our custom IUNICODE collation function conn.create_collation('IUNICODE', iUnicodeCollate) # run your query, business as usual cursor = conn.execute('select * from Songs')
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
# ...etc... The important bits are the definition of the iUnicodeCollate() function, and using conn.create_collation() to apply it to the db connection. And like I said, I don't know if this behavior matches that of the one implemented in MediaMonkey. It does work without any errors, and behaves how I think it should behave, which is good enough for me. :) If the Sqlite API in VB lets you define custom collations, this trick may work there as well. Unfortunately, I'm not well-versed in VB, and since my technique doesn't use ODBC I'm not even sure it'll translate to VB. Some relevant links: Sqlite docs on defining new collating sequences Python API docs for Sqlite connection objects Forum post by jiri in "sqlite db query error" which pointed me to the SQLite3_CreateCollation16() function.
WxPython Libreria per gestione di finestre derivata dalla libreria wxWindows (in C++). Nel tempo sono cambiate le convenzioni di denominazione: Standard attuale (nuovo dalla 2.5 in poi): · la libreria in toto si chiama "wx" · per adoperarla occorre import wx (che tra l'altro deve essere il primo import riferito alla libreria) · convenzione per i nomi: o la libreria è scritta in minuscolo (wx) o i metodi hanno maiuscola la prima lettera di ciascuna parola (e.g. MainLoop) [UpperCaseInterCap]; quando se ne derivano nuove classi, si consiglia di usare lo stesso standard o i nomi delle variabili di sistema sono minuscoli Precedente (vers. 2.4 e precedenti: utile per riconoscere esempi "vecchi") · la libreria si chiamava wxpython contenente il modulo wx · per adoperarla si usavano le seguenti espressioni, che però davano problemi di sovrapposizioni di nome o from wxpython import wx o from wxpython.wx import * · le parole chiave spesso iniziavano con le lettere wx (e.g. wxframe) ed appartenevano al modulo wx per cui si finiva per ripetere tali lettere: e.g. wx.wxFrame() [al posto dell'attuale wx.Frame() ] Terminologia: · windows : qualunque elemento (widget) di WxPython · frame : corrisponde alla classica finestra di Windows
Schema programma Premessa: le librerie rappresentano un magazzino di stampi (classi); esse vengono utilizzate per creare oggetti (derivati dalle classi) o, talora, per creare nuovi stampi (classi derivate) da cui ricavare nuovi tipi di oggetti. Ogni programma deve contenere almeno: · un oggetto applicazione
· un oggetto frame Possono esistere più oggetti (che chiama, purtroppo, window, ma che possono essere frame [finestre] o altri) "top level" (senza oggetti genitori), ma solo uno è il main top window (si specifica anche con il comando SetTop)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Per costruire un programma occorre: · importare la libreria wx · creare una nuova classe derivata dalla classe wx.application (come parametro alla App(..) verrà passato True se si vogliono gli errori in popup opre False se nello standard output; in compenso la clase deve riportare True sennò il programma si chiude) · definirne un metodo di inizializzazione OnInit() · creare un oggetto applicazione a partire dalla nuova classe · far partire il loop dell'applicazione All'inizio tutto appare un po' complesso perchè, per rendere modulare e leggibile il tutto, si lavoro molto su istanze di classi derivate dalle classi orginali wxpython. Nel far questo occorre tenere presenti le seguenti regole: · ogni metodo o proprietà della classe avrà sempre come primo parametro "self" oltre ai normali parametri (perchè in realtà i metodi derivati da da una classe sono rappresentati da una sola unica funzione, ma che si comporta diversamente in base a chi li chiama) · ogni classe ha un suo inizializzatore chiamato sempre ad ogni istanza (il metodo __init__) Nel caso la classe derivi da un'altra, occorre sempre chiamare il metodo __init__del "padre" (con gli stessi parametri) perchè a volte è necessario inizializzare correttamente il padre affinchè funzioni il figlio; da notare però che devi chiamarla così "nuda e cruda", cioè non devi creare una qualche istanza/oggetto con essa (sennò non finisci più!): e.g. wx.Frame.__init__(...) Non confondere il metodo OnInit() di wx.App() con quello __init__ di ogni oggetto della libreria wx: la OnInit () è un metodo virtuale chiamato dalla __init__ di wx.App () apposta per permetterci di definire l'ambiente iniziale (di per sè non fa nulla, dobbiamo farne l'override per adoperarla). Nella definizione del metodo figlio puoi specificare solo alcune variabili-parametro (con cui occorrerà richiamarla da parte di altri pezzi del programma), però poi nella __init__ dovrai chiamare correttamente il padre con quanto richiesto (al limite puoi usare alcuni dei parametri passati al figlio). In altre parole, è possibile creare una classe derivata con pochi parametri rispetto al padre, però poi nella __init__ del figlio, dove si chiama il padre, i parametri minimi necessari ci devono essere tutti. · nella prima riga di definizione della classe (class ...) occorre specificare solo la classe "padre" (mentre eventuali altri parametri appariranno nella definizione (e chiamata) dei vari metodi e proprietà (anche perchè chiamerai questi). In realtà quando viene creato un oggetto istanza della classe "derivata" potrà essere effettuata una "chiamata" con dei parametri, ma questi non sono specificati nella definizione della classe (class ...), bensì nel corrispondente metodo __init__ · qualunque widget ha come primi 2 parametri parent ed id (gli altri dipendono dal tipo di widget)
Esempio di applicazione minimale: #!/usr/bin/env python # -*- Encoding:Latin1 -*""" Programma per ... """ import wx # IMPORTA LA LIBRERIA class MiaClasseApp (wx.App): # CREA UNA SUB-CLASSE DELLA CLASSE MyApp def OnInit (self): # NE DEFINISCO LA ROUTINE DI INIZIALIZZAZIONE self.finestra = wx.Frame (parent=None, title='Titolo finestra') # DEFINISCO UN OGGETTO FINESTRA self.finestra.Show() # MOSTRO LA FINESTRA self.SetTopWindow(self.finestra) # IMPOSTO LA FINESTRA COME "PRINCIPALE" return True # FINE RIPORTANDO TUTTO BENE if __name__== '__main__': Applicazione = MiaClasseApp () APPLICAZIONE Applicazione.MainLoop ()
# INIZIALIZZO SOLO SE E' UN MODULO PRINCIPALE # CREO UN OGGETTO DERIVATO DALLA NUOVA CLASSE # FACCIO PARTIRE IL LOOP DEGLI EVENTI
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Se si vuole creare un programma ai minimi termini, esiste la classe wx.PySimpleApp() usabile come segue per evitare la definizione di una classe di applicazione: Applicazione = wx.PySimpleApp()
wx.ArtProvider Questa è la risorsa "interna" di wxpython contenente le bitmap standard per i pulsanti. Grazie ad essa è possibile accedere a bitmap predefinite oppure, facendo un override (derivazione e cambiamento), è possibile modificare l'aspetto anche delle immagini standard dei pulsanti di wxpython. Ecco un elenco delle risorse diponibili: self.art_list = [ wx.ART_ADD_BOOKMARK, wx.ART_DEL_BOOKMARK, wx.ART_HELP_SIDE_PANEL, wx.ART_HELP_SETTINGS, wx.ART_HELP_BOOK, wx.ART_HELP_FOLDER, wx.ART_HELP_PAGE, wx.ART_GO_BACK, wx.ART_GO_FORWARD, wx.ART_GO_UP, wx.ART_GO_DOWN, wx.ART_GO_TO_PARENT, wx.ART_GO_HOME, wx.ART_FILE_OPEN, wx.ART_FILE_SAVE, wx.ART_FILE_SAVE_AS, wx.ART_PRINT, wx.ART_HELP, wx.ART_TIP, wx.ART_REPORT_VIEW, wx.ART_LIST_VIEW, wx.ART_NEW_DIR, wx.ART_HARDDISK, wx.ART_FLOPPY, wx.ART_CDROM, wx.ART_REMOVABLE, wx.ART_FOLDER, wx.ART_FOLDER_OPEN, wx.ART_GO_DIR_UP, wx.ART_EXECUTABLE_FILE, wx.ART_NORMAL_FILE, wx.ART_TICK_MARK, wx.ART_CROSS_MARK, wx.ART_ERROR, wx.ART_QUESTION, wx.ART_WARNING, wx.ART_INFORMATION, wx.ART_MISSING_IMAGE, wx.ART_COPY, wx.ART_CUT, wx.ART_PASTE, wx.ART_DELETE, wx.ART_NEW, wx.ART_UNDO, wx.ART_REDO, wx.ART_QUIT, wx.ART_FIND,
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
wx.ART_FIND_AND_REPLACE ]
( l'indirizzo del programma che crea l'immagine sopra: http://www.python-forum.org/pythonforum/viewtopic.php?f=2&t=10539 )
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
wx,Frame wx.Frame corrisponde alle finestre di Windows. Pg. 41 La posizione e la dimensione sono specificate da specifici classi assimilabili a tuple di 2 valori (pos e size) che però dispongono rispettivamente delle proprietà .x e .y, nonchè .height e .width . L'origine delle coordinate (0,0) è in alto a sinistra. L'aspetto della finestra è definibile anche con lo stile: style=wx.MAXIMIZE oppure wx.DEFAULT_FRAME_STYLE NOTA: NEGLI ESEMPI SEGUENTI DEVI METTERE UN PUNTO "." DOPO wx e.g. wx.DEFAULT_FRAME_STYLE Window styles wx.DEFAULT_FRAME_STYLE Defined as wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN. wxICONIZE Display the frame iconized (minimized). Windows only. wxCAPTION Puts a caption on the frame. wxMINIMIZE Identical to wxICONIZE. Windows only. wxMINIMIZE_BOX Displays a minimize box on the frame. wxMAXIMIZE Displays the frame maximized. Windows only. wxMAXIMIZE_BOX Displays a maximize box on the frame. wxCLOSE_BOX Displays a close box on the frame. wxSTAY_ON_TOP Stay on top of all other windows, see also wxFRAME_FLOAT_ON_PARENT. wxSYSTEM_MENU Displays a system menu. wxRESIZE_BORDER Displays a resizeable border around the window. wxFRAME_TOOL_WINDOW Causes a frame with a small titlebar to be created; the frame does not appear in the taskbar under Windows or GTK+. wxFRAME_NO_TASKBAR Creates an otherwise normal frame but it does not appear in the taskbar under Windows or GTK+ (note that it will minimize to the desktop window under Windows which may seem strange to the users and thus it might be better to use this style only without wxMINIMIZE_BOX style). In wxGTK, the flag is respected only if GTK+ is at least version 2.2 and the window manager supports _NET_WM_STATE_SKIP_TASKBAR hint. Has no effect under other platforms. wxFRAME_FLOAT_ON_PARENT The frame will always be on top of its parent (unlike wxSTAY_ON_TOP). A frame created with this style must have a non-NULL parent. wxFRAME_EX_CONTEXTHELP Under Windows, puts a query button on the caption. When pressed, Windows will go into a context-sensitive help mode and wxWidgets will send a wxEVT_HELP event if the user clicked on an application window. Note that this is an extended style and must be set by calling SetExtraStyle before Create is called (two-step construction). You cannot use this style together with wxMAXIMIZE_BOX or wxMINIMIZE_BOX, so you should use wxDEFAULT_FRAME_STYLE & ~ (wxMINIMIZE_BOX | wxMAXIMIZE_BOX) for the frames having this style (the dialogs don't have a minimize or a maximize box by default) wxFRAME_SHAPED Windows with this style are allowed to have their shape changed with the SetShape method. wxFRAME_EX_METAL On Mac OS X, frames with this style will be shown with a metallic look. This is an extra style. The default frame style is for normal, resizeable frames. To create a frame which can not be resized by user, you may use the following combination of styles: wxDEFAULT_FRAME_STYLE & ~ (wxRESIZE_BORDER | wxRESIZE_BOX | wxMAXIMIZE_BOX). See also window styles overview. In genere vi si inserisce un pannello (wx.Panel) che permette maggiore controllo di aspetto (tra cui il colore dello sfondo, altrimenti grigio). E' possibile inoltre aggiungere un menu, una toolbar ed una status-bar. Da notare il singolare gemellaggio tra menu e toolbar che condividono la tipologia di eventi (wx.EVT_MENU)
Sizers Sono oggetti che permettono di creare un'interfaccia grafica in grado di adattarsi alle variazioni di dimensione del frame (finestra). Il concetto di base è: · creare un sizer · attribuirgli le sotto-finestre (o altri sizer) che deve controllare · chiama il metodo SetSizer(sizer) per renderlo operativo
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Tipologie di sizer
· wx.BoxSizer: elementi allineati in file (orizzontale o verticale) o wx.StaticBoxSizer: basata sul precedente, ma con un bordo ed un titolo opzionale
· wx.GridSizer: griglia 2D con elementi tutti uguali o wx.FlexGridSizer: l'ampiezza di ciascuna riga e di ciascuna colonna è determinata dall'elemento più grande
o wx.GridBagSizer: basata sul precedente, permette di posizionare più liberamente gli oggetti, facendo occupare anche più posti
La modalità di ridimensionamento è controllata da 2 parametri: · lo stretch-factor che controlla il ridimensionamento secondo l'asse principale del sizer o 0 : dimensioni fisse o n : entità di compartecipazione allo spazio disponibile (considerato lo stretch-factor di altri elementi: immagina che il nuovo spazio disponibile venga diviso per la somma di tutti gli stretch-factor e quindi le parti vengano assegnate in base all'entità di tale fattore)
· il bitmask flag controlla il ridimensionamento dell'asse perpendicolare a quello principale:
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
o wx.EXPAND : riempie tutto lo spazio disponibile
CONSIGLIO: se l'aspetto dei sizer non è quello atteso, provare a colorare lo sfondo degli elementi in modo da vederne chiaramente la posizione Reference: http://www.wxpython.org/docs/api/wx.Sizer-class.html http://wiki.wxpython.org/UsingSizers
Reference Per conoscere la sintassi dei comandi, guarda sul reference di wxpython i parametri del metodo __init__ : quelli indispensabili sono quelli senza un valore predefinito (cioè senza assegnazione con = ).
Toolbar wx.Toolbar E' un contenitore di pulsanti che vengono posizionati automaticamente nella porzione superiore. Si possono aggiungere elementi in 2 modi: · il più semplice: AddSimpleTool() cui basta specificare: o id o bitmap o short-text (per il tooltip dell'help) o longtext (per l'help nella statusbar) · AddTool () Per far apparire la toolbar occorre: frame.CreateToolBar() # CREA LA TOOLBAR (metodo del frame); è possibile passare diversi style (pg. 164) e.g. wx.TB_TEXT permette di far apparire anche il testo insieme all'icona CreateToolBar(long style = wxNO_BORDER | wxTB_HORIZONTAL, wxWindowID id = -1, const wxString& name = "toolBar") ATTENTO ALLE LETTERE MAIUSCOLE NEL TERMINE CreateToolBar !!
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
AddSimpleTool (id, bitmap, short-text, longtext) #AGGIUNTA ELEMENTO (metodo rapido) AddTool () # AGGIUNTA ELEMENTO (compresa seconda bitmap pressed e dati associati) AddCheckTool() # AGGIUNTA ELEMENTO (come checkbox) AddRadioTool() # AGGIUNTA ELEMENTO (come radiobox) Realize() composizione) Show()
# CALCOLA LA DISTRIBUZIONE DEGLI ELEMENTI (da richiamare ogni volta che se ne varia la # MOSTRA LA TOOLBAR
Eventi Nello specificare la routine da chiamare con l'evento (con Bind) NON devi assolutamente mettere le parentesi alla routine da chiamare, altrimenti la chiama subito interpretandola come una semplice funzione il cui risultato darĂ l'indirizzo della routine cui saltare in caso di evento. Alla routine associata viene passato in automatico almeno il parametro "evento" (in taluni esempi preceduto dal self,ma non nella mia esperienza). Per ricavare caratteristiche da tale variabile ci si applica .GetEventObject() su cui poi operare con appositi metodi/proprietĂ , ad esempio: event.GetEventObject().GetLabel() per ricavare l'etichetta del pulsante che ha scatenato l'evento
Button Per cambiare il colore Pulsante1.SetBackgroundColour('gray') Ecco alcuni colori disponibili: ['blue', 'red', 'yellow', 'orange', 'green', 'purple', 'navy blue', 'black', 'gray' Per cambiare il font della scritta, adopera il metodo SetFont(pointSize, family, style, weight, underline, face, encoding) e.g. Pulsante1.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, weight=wx.FONTWEIGHT_BOLD)) Reference: http://www.wxpython.org/docs/api/wx.Font-class.html
Timer Oltre alla funzione timer, sono disponibili delle funzioni semplici per chiamare una sola volta una routine dopo tot tempo: CallLater ed il suo alias FutureCall
Message & dialogs Per far apparire una finestra di messaggio semplice, basta la linea sottostante (senza istanziare oggetti) wx.MessageBox( "Messaggio", "Titolo")
Colori There are three ways for setting colours. We can create a wx.Colour object, use a predefined colour name or use hex value string. SetBackgroundColour(wx.Colour(0,0,255)) SetBackgroundColour('BLUE') SetBackgroundColour('#0000FF') Predefined colour names in wxPython: * wx.BLACK * wx.WHITE * wx.RED * wx.BLUE * wx.GREEN
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
* wx.CYAN * wx.LIGHT_GREY
Refresh Depending on how you have you application set up, you can call > > Refresh with "self" or with "self.panel" or "self.frame" or even > > "self.btn.GetParent().Refresh()"
PyQt4 Libreria grafica basata sulle librerie Qt; la versione per Python (PyQt). Sembra essere fondamentale importare correttamente i sottomoduli e.g. from PyQt4 import QtGui ed inizializzare sempre l'applicazione Qt app=QtGui.QApplication(sys.argv) Esempio funzionante: import sys from PyQt4 import QtGui app = QtGui.QApplication(sys.argv) widget = QtGui.QWidget() widget.resize(250, 150) widget.setWindowTitle('simple') widget.show() sys.exit(app.exec_())
pyuic4 Pyuic4.exe permette di convertire il file .ui (creato dal Designer Qt) in file .py pyuic4 [options] .ui-file Opzioni: -o FILE, --output=FILE Scriverà su file il codice Python -p, --preview Viene creata e mostrata la GUI senza generare codice Python -x, --execute Specifica che verrà aggiunto al codice Python (se creato con l'opzione -o ) anche del codice per rendere eseguibile la GUI Esempio: pyuic4.lnk k:\cancella\mioprova.ui -x -o k:\cancella\mio.py crea ilfile mio.py che sarà direttamente eseguibile -h, --help Mostra l'help --version Mostra il n. di versione -i N, --indent=N Il file python avrà indentazione=N; se N=0, viene usato il Tab (default= 4 spazi) --from-imports I moduli resource vengono importati con il comando from . import al posto di un semplcie import.
QtDesigner E' un programma che permette di creare interfacce grafiche (ma anche singole finestre o componenti) e salvare il risultato in un file XML .ui Quest'ultimo file può poi essere convertito in codice (C++, Python,..) da apposite utility (uic.exe per il C++, pyuic4.exe nel caso di Python). Tramite la classe QUiloader è possibile caricare dinamincamente le interfacce. Sul designer quello che puoi fare è creare l'interfaccia grafica (mettendo i widget e settando le proprietà), poi puoi connettere i widget alle slot e creare le QAction (per i menu ad esempio). Il codice prodotto ha le seguenti caratteristiche:
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
· viene creata una singola classe (definita form class) di tipo object avente come nome (preceduto da Ui_) quello ·
dell'oggetto toplevel nel Designer la form class contiene il metodo setupUi che riceve come parametro il widget in cui viene creata l'interfaccia utente; la tipologia (QDialog, QWidget, QmainWindow) viene specificata in Designer e ci si riferisce ad esso come Qt base class
Il codice creato può essere utilizzato in più modi: ecco degli esempi riguardanti un file ui_imagedialog.py contenente un oggetto ImageDialog di tipo QDialog. Approccio diretto: import sys from PyQt4 import QtGui from ui_imagedialog import Ui_ImageDialog
# Importo le librerie di sistema e delle PyQt4 (QTGui)
app = QtGui.QApplication(sys.argv) window = QtGui.QDialog() ui = Ui_ImageDialog() creata) ui.setupUi(window)
# Creo un'applicazione derivandola da QApplication # Creo un elemento window derivato da QDialog # Creo ui derivandolo dalla classe Ui_ImageDialog (l'interfaccia grafica
window.show() sys.exit(app.exec_())
# Mostro l'elemento window # Eseguo il programma (ed esco una volta terminato)
# Importo l'interfaccia grafica creata
# e ne chiamo il metodo setupUi ()
-----------------------------------------------------------------------------------------------------------------------------------------------------------------Approccio ad eredità multipla (qualcuno consiglia questo metodo perchè permette di usare il codice .ui senza modifiche): from PyQt4 import QtCore, QtGui from ui_imagedialog import Ui_ImageDialog
# Importo le librerie di PyQt4 necessarie (QTCore e QTGui) # Importo l'interfaccia grafica creata
class ImageDialog(QtGui.QDialog, Ui_ImageDialog): il tipo QDialog e def __init__(self): aggiuntivi dell'interfaccia grafica QtGui.QDialog.__init__(self)
# Definisco una classe ImageDialog passando come parametri # Solito metodo di inizializzazione dove definisco i dettagli
# Set up the user interface from Designer. self.setupUi(self) # Make some local modifications. self.colorDepthCombo.addItem("2 colors (1 bit per pixel)") # Connect up the buttons. self.connect(self.okButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("accept()")) self.connect(self.cancelButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("reject()")) -----------------------------------------------------------------------------------------------------------------------------------------------------------------The second example shows the single inheritance approach where we sub-class QDialog and set up the user interface in the __init__() method: from PyQt4 import QtCore, QtGui from ui_imagedialog import Ui_ImageDialog class ImageDialog(QtGui.QDialog): Created with the Freeware Edition of HelpNDoc: Free help authoring environment
def __init__(self): QtGui.QDialog.__init__(self) # Set up the user interface from Designer. self.ui = Ui_ImageDialog() self.ui.setupUi(self) # Make some local modifications. self.ui.colorDepthCombo.addItem("2 colors (1 bit per pixel)") # Connect up the buttons. self.connect(self.ui.okButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("accept()")) self.connect(self.ui.cancelButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("reject()")) It is also possible to use the same approach used in PyQt v3. This is shown in the final example: from PyQt4 import QtCore, QtGui from ui_imagedialog import ImageDialog class MyImageDialog(ImageDialog): def __init__(self): ImageDialog.__init__(self) # Make some local modifications. self.colorDepthCombo.addItem("2 colors (1 bit per pixel)") # Connect up the buttons. self.connect(self.okButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("accept()")) self.connect(self.cancelButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("reject()")) For a full description see the Qt Designer Manual in the Qt Documentation.
Bibliografia: http://riverbankcomputing.com/static/Docs/PyQt4/pyqt4ref.html#using-qt-designer
Image library Image.new(mode, size) Image.new(mode, size, color) Creates a new image with the given mode and size. 路 Size is given as a (width, height)-tuple, in pixels. 路 Color is given as a single value for single-band images, and a tuple for multi-band images (with one value for each band). In 1.1.4 and later, you can also use color names (see the ImageColor module documentation for details) If the color argument is omitted, the image is filled with zero (this usually corresponds to black). If the color is None, the image is not initialised. This can be useful if you're going to paste or draw things in the image. from PIL import Image im = Image.new("RGB", (512, 512), "white")
Image.open(file)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Image.open(file, mode) Opens and identifies the given image file. This is a lazy operation; the function reads the file header, but the actual image data is not read from the file until you try to process the data (call the load method to force loading). If the mode argument is given, it must be “r”. You can use either a string (representing the filename) or a file object as the file argument. In the latter case, the file object must implement read, seek, and tell methods, and be opened in binary mode.
Image.blend(image1, image2, alpha) Creates a new image by interpolating between the given images, using a constant alpha. Both images must have the same size and mode. out = image1 * (1.0 - alpha) + image2 * alpha · If the alpha is 0.0, a copy of the first image is returned. · If the alpha is 1.0, a copy of the second image is returned. There are no restrictions on the alpha value. If necessary, the result is clipped to fit into the allowed output range. Per una funzione simile cìè anche composite Image.composite(image1, image2, mask) => image Creates a new image by interpolating between the given images, using the mask as alpha. The mask image can have mode "1", "L", or "RGBA". All images must be the same size. E c'è anche paste paste im.paste(image, box) Pastes another image into this image. The box argument is either a 2-tuple giving the upper left corner, a 4-tuple defining the left, upper, right, and lower pixel coordinate, or None (same as (0, 0)). If a 4-tuple is given, the size of the pasted image must match the size of the region. If the modes don't match, the pasted image is converted to the mode of this image (see the convert method for details Per ricavare le dimensioni: w, h = img.size mode im.mode => string Image mode. This is a string specifying the pixel format used by the image. Typical values are "1", "L", "RGB", or "CMYK." crop im.crop(box) => image Returns a rectangular region from the current image. The box is a 4-tuple defining the left, upper, right, and lower pixel coordinate.(nota non si passa la larghezza/altezza del rettangolo, ma le coordinate assolute dei due estremi; inoltre, nota che si passano 4 valori divisi da virgole, non riuniti a coppie) This is a lazy operation. Changes to the source image may or may not be reflected in the cropped image. To get a separate copy, call the load method on the cropped copy.
save im.save(outfile, options...) im.save(outfile, format, options...) Saves the image under the given filename. If format is omitted, the format is determined from the filename extension, if possible. This method returns None. Keyword options can be used to provide additional instructions to the writer. If a writer doesn't recognise an option, it is silently ignored. The available options are described later in this handbook. Created with the Freeware Edition of HelpNDoc: Free help authoring environment
You can use a file object instead of a filename. In this case, you must always specify the format. The file object must implement the seek, tell, and write methods, and be opened in binary mode. If the save fails, for some reason, the method will raise an exception (usually an IOError exception). If this happens, the method may have created the file, and may have written data to it. It's up to your application to remove incomplete files, if necessary. im = Image.open(infile) im.thumbnail(size) im.save(outfile, "JPEG") Questo fa una conversione al volo! Image.open(infile).save(outfile)
import Image global ext ext = ".jpg" imageFile = "test.jpg" im1 = Image.open(imageFile)
let's try creating a new image with two copies of an image import Image img = Image.open("kamioka.png") def mirror(img, n=2): x,y = img.size mirror_img = Image.new("RGB", (x*n,y), "White") for i in range(0, n): mirror_img.paste(img, (i*x,0)) return mirror_img Which we can then use to create an image with two copies. img = Image.open("kamioka.png") mirror(img).save("kam3.png") We can also use it to make an image with a few more copies. >>> img = Image.open("kamioka.png") img = Image.open("kamioka.png") >>> mirror(img, n=5).save("kam3_2.png") mirror(img).save("kam3_2.png") Aggiungiamo un bordo monocromatico: def border(img, width=10, color="White"): x,y = img.size bordered = Image.new("RGB", (x+(2*width), y+(2*width)), color) bordered.paste(img, (width, width)) return bordered
You can use the Image.paste(imagesrc, box) method PIL-doc Image.Image.paste OOOOOH, putpixel places an image? Or does it draw a dot? I guess it's time to experiment... An image is made up of dots.
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
im.paste(image, box) Pastes another image into this image. The box argument is either a 2-tuple giving the upper left corner, a 4-tuple defining the left, upper, right, and lower pixel coordinate, or None (same as (0, 0)). If a 4-tuple is given, the size of the pasted image must match the size of the region. If the modes don't match, the pasted image is converted to the mode of this image (see the convert method for details). im.paste(colour, box) Same as above, but fills the region with a single colour. The colour is given as a single numerical value for single-band images, and a tuple for multi-band images. im.paste(image, box, mask) Same as above, but updates only the regions indicated by the mask. You can use either “1”, “L” or “RGBA” images (in the latter case, the alpha band is used as mask). Where the mask is 255, the given image is copied as is. Where the mask is 0, the current value is preserved. Intermediate values can be used for transparency effects. Note that if you paste an “RGBA” image, the alpha band is ignored. You can work around this by using the same image as both source image and mask. VEDI PERO' ANCHE NUOVO COMANDO DA 1.1.5 putalpha # im.putalpha(band) Copies the given band to the alpha layer of the current image. The image must be an “RGBA” image, and the band must be either “L” or “1”. (New in PIL 1.1.5) You can use putalpha on other modes as well; the image is converted in place, to a mode that matches the current mode but has an alpha layer (this usually means “LA” or “RGBA”). Also, the band argument can be either an image, or a colour value (an integer).
Im.putpixel(xy, colour) Modifies the pixel at the given position. The colour is given as a single numerical value for single-band images, and a tuple for multi-band images. Note that this method is relatively slow. If you're using 1.1.6, pixel access objects (see load) provide a faster way to modify the image. If you want to generate an entire image, it can be more efficient to create a Python list and use putdata to copy it to the image. For more extensive changes, use paste or the ImageDraw module instead. You can speed putpixel up a bit by “inlining” the call to the internal putpixel implementation method: im.paste(colour, box, mask) Same as above, but fills the region indicated by the mask with a single colour. VEDI: http://lethain.com/entry/2010/jan/04/a-photo-album-with-python-and-pil/ http://www.riisen.dk/dop/pil.html http://www.pythonware.com/products/pil/
Tkinter Libreria grafica di serie con Python, apparentemente semplice, ma anche questa ha i suoi casini.. Da molti editor (idle, pyscripter,..) fallisce l'esecuzione con un messaggio di "module" che non vanno (sembra che ad incasinare sia il .mainloop() necessario se si eseguono gli script standalone senza IDE); commentalo se li fai funzionare
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
da editor Talora è necessario convertire le variabili di python in tipi di variabili specifici di Tkinter, apparentemente dei doppioni ma forse legati al fatto che la libreria Tkinter non è nata per Python per cui ha dei formati "interni" diversi nel tenere le variabili e nel porting non è stato possibile fare tutto in maniera trasparente. Ad esempio, per popolare una listbox direttamente sfruttando un elenco di strnghe di Python occorre convertirlo prima nel formato Tkinter.StringVar ElencoPerTk= Tkinter.StringVar(value=elenco) Esempi miei di utilizzo di Tkinter sono nel modulo basic import Tkinter finestra_principale=Tkinter.Tk() # definisce una nuova finestra etichetta=Tkinter.Label(finestra_principale, "Questo e' un messaggio") # crea una label etichetta.pack() # E' un metodo del singolo widget (non della finestra): in pratica dice di affidarsi al layout manager (che si chiama packager) etichetta.mainloop() # strano, il loop è sul componente, eppure... Volendo, è possibile mettere .pack() in coda al comando del widget, e.g. Tkinter.Label(finestra_principale, "Questo e' un messaggio") # crea una label Spesso nel far apparire un widget/finestra, rimane aperta una finestra più grossa sotto: per farla sparire, usa il codice seguente: finestra=Tkinter.Tk() finestra.withdraw() # faccio sparire la finestra root e quindi usa finestra come root dei tuoi widget che comunque appariranno Per farla riapparire si usa il comando .deiconify()
Per gestire la visualizzazione di un testo, si usa Tkinter.Text() Per inserirvi il testo si usa il comando insert (indice, testo) dove indice è una stringa in cui ci possono andare un sacco di cose, tra cui le coordinate di inserzione nel formato "x.y" (nota la divisione con il punto "." ) t.insert("1.0","Vediamo se va!") In realtà è un widget molto avanzato con tag e funzioni di scrolling (pensaci per ViewCRD) Vedi http://www.pythonware.com/library/tkinter/introduction/x7883-concepts.htm Questo esempio sotto funziona (orribile la scelta dei nomi delle variabili!): import Tkinter zz=Tkinter.Tk() z=Tkinter.Frame(zz) z.pack() y=Tkinter.Text(z,height=30,width=80,background='brown') # Aggiungo il componente text per l'output y.insert(Tkinter.END,"Vediamo se va!") y.pack() y.mainloop() mainloop() CREDO CHE mainloop() VADA MESSA SEMPRE COME ULTIMA ISTRUZIONE (se la metto dopo, viene ignorata o dà addirittura errore); in alcuni casi sembra pure opzionale... We start the Tkinter event loop. Notice that the Python >>> prompt has now disappeared. That tells us that Tkinter now has control. If you press the Quit button the prompt will return, proving that our command option worked. Don't expect the window to close, the python interpreter is still running and we only quit the mainloop function, the various widgets will be destroyed when Python exits - which in real programs is usually immediately after the mainloop terminates! Note that if running this from Pythonwin or IDLE you may get a slightly different result, if so try typing the commands so far into a Python script and running them from an OS command prompt. pack()
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
The pack() method invokes a Layout Manager known as the packer which is very easy to use for simple layouts but becomes a little clumsy as the layouts get more complex. We will stick with it for now because it is easy to use. Note that widgets will not be visible in our application until we pack them (or use another Layout manager method). Esiste una sotto-libreria di Tkinter che si chiama tkMessageBox, che va usata importandola con: import tkMessageBox Essa permette di far comparire dei dialoghi già pronti, ad esempio: tkMessageBox.showwarning("Open file", "Cannot open this file\n") # mostra una finestra con il punto esclamativo ed il pulsante ok ma esistono anche per info ed alert I thought it might be worth mentioning here that the examples as given will (at least on my Windows XP system with Python 2.5) pop up a blank "root" window as well as the requested dialog, which is not ideal if you just want to show a dialog in a program that otherwise doesn't have a GUI. To get just the dialog with no root window appearing, you can do, e.g.: import Tkinter, tkMessageBox root = Tkinter.Tk() root.withdraw() # withdraw significa allontanare: probabilmene fa sparire la finestra root tkMessageBox.showinfo("my dialog title", "my dialog message")
Esiste un'altra sottolibreria tkSimpleDialog per i dialoghi Yes/No,,,, Esiste un'altra sottolibreria Tix che permette di fare altre cose (dialoghi di scelta, progress bar): Esempio di progress bar (che di fatto è una nuova finestra): import Tix # Non serve esplicitamente importare Tkinter, basta Tix k=Tix.Tk() # NOTA: USA LA DEFINIZIONE DI FINESTRA Tk() DELLA LIBRERIA TIX, NON TKINTER!!!! x=Tix.Meter(k) x.pack() x.mainloop() # SENZA QUESTO NON APPARE!! Esempi di Tix.Meter: http://www.velocityreviews.com/forums/t363972-newbie-doing-lengthy-initialization-with-tkinter-gui.html inoltre Tkinter permette di settare un timer, dialoghi per scelta colore, nome file,... Vedi: · http://www.java2s.com/Code/Python/GUI-Tk/showwarningDialogbox.htm · http://www.pythonware.com/library/tkinter/introduction/standard-dialogs.htm · http://tk-happy.sourceforge.net/tk_dialogs.html
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Impostazione documento Note sulla impostazione grafica di questo documento (per renderne omogenea la stesura nel tempo)
· · · · · · · ·
Non occorre riportare il nome del topic nel testo (già lo mette in automatico HelpNDoc) I nomi delle sottosezioni sono in Arial 11 blu bold Sottosezione Il testo normale in Arial 10; le parti più significative saranno in bold Il codice sarà in Arial 10 verde italico con le parole chiave in bold; in caso di più esempi di seguito, si useranno tonalità di verde diverse Eventuali riquadri possono essere definiti come sfondi di paragrafo con bordo nero I riferimenti al Python 3 andranno in Arial 10 rosso. Per attrarre l'attenzione, si può usare il colore lilla. Particolarità di Phyton in Arial 10 con sfondo giallo
Created with the Freeware Edition of HelpNDoc: Free help authoring environment
Numeri Numeri casuali Si ottengono tramite il modulo random che presenta numerose funzioni suddivise per numeri interi, reali e sequenze. Per numeri interi: random.randint (a, b) Restituisce un intero casuale tra a e b (compresi)
Created with the Freeware Edition of HelpNDoc: Free help authoring environment