Archivi Categorie: Python

Filter con Python

filterUna cosa urgente (!) a completamento del post precedente. Quando c’è un’emergenza eccomi! E se poi la richiesta fosse comparsa sul blog (ci sono i commenti apposta per quello) sarebbe ancora meglio.

Domanda:
In Linux ci sono parecchi comandi che leggono da tastiera e scrivono sul monitor, tipo echo:

0

Si può fare una cosa simile con Python?

Risposta:
Cerrrto!
Questi comandi si chiamano filtri. “In Unix and Unix-like operating systems, a filter is a program that gets most of its data from its standard input (the main input stream) and writes its main results to its standard output (the main output stream). Unix filters are often used as elements of pipelines. [...] Common Unix filter programs are: cat, cut, grep, head, sort, uniq, and tail.dice la Wiki. Sì c’è anche in italiano ma la versione inglese mi piace di più.
E per farlo con Python c’è già tutto online, su Stack Overflow.

#!/usr/bin/python
<pre># -*- coding: utf-8 -*-

import sys

for line in sys.stdin:
    sys.stdout.write(line)

1

D: Ma non si vede la differenza da prima, con echo liscio!

R: Sì ma se ti metto una pipe, così:

2

e dopo puoi fare anche questo:

3

Ecco, filtri archiviati (credo) :roll:

Modificare il testo con Python

re

Le espressioni regolari –d’ora in poi RE– non è che sono semplicissime. Vanno prese a piccole dosi, quasi omeopatiche come nel post precedente.

Oggi vediamo di riscrivere gli script con un linguaggio serio, Python. Non che io non consideri serio newLISP ma ho visto che il solo nominarlo fa venire l’orticaria alla gente.

Prossimamente affronteremo più razionalmente le RE ma per adesso tutto quello che ci serve è sapere che c’è il modulo re di cui utilizzeremo i metodi compile() e sost().

Ecco dpv.py, lo script per sostituire i punti-virgola son spazi:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, re

if len(sys.argv) < 2:
	print "uso: ", sys.argv[0], "file-dei-dati"
	sys.exit(2)
if not os.path.isfile(sys.argv[1]):
	print "manca il file ", sys.argv[1]
	sys.exit(2)

txt = open(sys.argv[1], 'r').read()

p = re.compile(';')
print p.sub(' ', txt)

0

Si potrebbe trattare in modo simile il file con i dati separati da tab, basta modificare la riga 15, sostituendo ; con \t.

Però possiamo fare un passo in più: scrivere la RE che trovi (come si dice match, no, non fiammifero) sia il punto-virgola che il tab, ecco dsost.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, re

if len(sys.argv) < 2:
	print "uso: ", sys.argv[0], "file-dei-dati"
	sys.exit(2)
if not os.path.isfile(sys.argv[1]):
	print "manca il file ", sys.argv[1]
	sys.exit(2)

txt = open(sys.argv[1], 'r').read()

p = re.compile(';|\t') # qui!
print p.sub(' ', txt)

1

Sì, rispetto allo script precedente cambia solo la riga 15.

E, non so come la pensate voi ma secondo me, le RE non sono poi così perverse. C’è gente che le maneggia continuamente, i perlisti :roll:

Cast –quasi– in Python

Il post Un esercizio in Python ha dato il via a un paio di commenti che se fossi ripetitivo scriverei ancora una volta “Quando il gioco si fa duro…”.
bbE invece no!
Poi ci dev’essere un epidemia (forse per qualche congiunzione astrale (Rosetta?)) ma mi sono trovato alle prese con i cast, cosa che in Python non è che si chiamano proprio così, adesso mi spiego.
Sì perché il blog va bene quando ci sono gli über-nerd che usano le regexp (re, regular expressions) o lambda e list comprehensions ma poi il resto di noi resta a bocca aperta con la testa che gira (o è tutto il mondo intorno?).
Allora facciamo che di regexp ne parlo un’altra volta, e anche di Emacs, va benissimo Geany per Python (certo, si trova anche per Windows).

Allora il cast, o typecast. In C sarebbe comunissimo trovare cose come:

float pi; int ip;
pi = 22.0 / 7.0;
ip = (int) pi;

che fa proprio quello che serve. In Python c’è qualcosa di ancora più bello:

0

ecco, il passaggio da tupla a lista è questione di un cast.
Vediamo per la lettura dei dati, in modo interattivo nell’esempio ma è la stessa cosa a leggere un file:

1

OK? Ovviamente posso usare la list comprehension per il ciclo di conversione:

2

Inoltre le virgole nell’input non sono necessarie, va però modificato il parametro di split():

3

Un’ultima cosa: nella versione 3.x raw_input() è diventata input().

Questo, come già detto, per tutti quelli che non hanno la patente di nerd informatici, per quelli che hanno altri interessi e usano la programmazione solo quando necessario e per quello che gli serve.
Pensa te che invece c’è chi insiste con la programmazione funzionale, magari in Lisp, vedi Clojure per esempio. A proposito avete sentito le novità di hy, dove il Lisp è accoppiato a Python, usi Python come se fosse Lisp e viceversa –OK, smetto subito, anzi cancello :oops: :mrgreen:

Un corso di Python su YouTube

L’amico Luigi Bit3Lux mi segnala un corso di Python su YouTube. Bello. Ecco, se adesso vi do subito il link partite immediatamente senza finire di leggere il post. E io poi mi ritrovo a chiedermi “che si sto a fare? qual è il mio ruolo nell’universo?”. Allora niente, dovete pazientare fino alla fine del post.
Prima le condizioni al contorno, come dicono i mate.

marco-ridottoBeh, c’è una autobio qui che rimanda a qui più dettagliata. OK, un informatico, pythonista e –più importante– pastafariano.

Volendo si potrebbe seguire il suo blog, Taifu.
Da dove viene Taifu? Mystero mysteryouso, è anche il suo nick su Twitter, volendo si potrebbe chiederglielo, chissà.

OK, basta ambientazione, il corso. Lo trovate qui: Programmare in Python 2.
Marco è davvero bravo, chi vuole cominciare con Python farebbe bene a seguirlo.
Anche perché tutto il corso su YouTube è in italiano, non avete più scuse. E qui un appunto: il “van” di “Guido van Rossum” si deve pronunciare “fan”, come fanno gli olandesi; è l’unica imprecisione che ho trovato.

Siccome il corso è davvero bello questo post lo pubblico anche su Lubit Linux, due piccioni con una fava :razz: :shock: :roll:

Dov’è il modulo?

Una richiesta a seguito del post Intro all’uso dei moduli in Python.

Dovresti dire anche come fa python a trovare i file da importare sul file system. Con java è semplice e complicato allo stesso tempo, e con python?

Beh, con Python è semplice (tutto è semplice con Python) e complicato allo stesso tempo: Python non ha niente da invidiare a Java quando ci si mette :twisted:

sherlock_holmes

Ecco quello che so. Uso la versione 3.x perché con la 2.x la variabile sys.path sarebbe molto lunga (ho caricato parecchi componenti aggiuntivi tra i quali scipy/numpy che consiglio caldamente), l’unica differenza (in questo caso) è di mettere le parentesi a print.

Per il test ho creato un modulo elementare ecco3.py nella directory ~/lab

def eccomi():
	print("eccomi!")

La cosa più semplice sarebbe l’uso della variabile d’ambiente PYTHONPATH.
Normalmente non ha alcun valore e allora otteniamo:

0

Come si vede nella lista la directory ‘/home/juhan/lab‘ non c’è ma settando PYTHONPATH ottengo:

1

OK! funziona. Caso risolto. Quasi.

2

o anche

3

No, l’usuale scorciatoia ‘~‘ Python non la digerisce. In effetti credo che il problema sia a livello della shell, ho cercato su StackOverflow e ci sono parecchie discussioni, lunghe e poco sexy.

Ma esiste un’altra via, che preferisco, programmatica:

import sys, os

print('inizio:', sys.path)
mymodir = os.path.expanduser("~/lab")
print('\nla mia dir personale dei moduli aggiuntivi:', mymodir)
sys.path.append(mymodir)
print('dopo  :', sys.path)
print("\ntrovata all'indice", sys.path.index(mymodir))
import ecco3
ecco3.eccomi()

d3

~/lab‘ viene normalizzato con expanduser(), riga 4 e aggiunto alla lista sys.path, riga 6.

Semplice vero? :shock: perché Python rockz :roll: da oggi usiamo solo più quello. E Octave, Java, C++, Go, Javascript, … :mrgreen:

Un esercizio in Python

A me piace molto il C++, ci lavoro e lo insegno. Ma riconosco che sia un linguaggio “un po’ complicato” (eufemismo). Per tante cose di tutti giorni, serve qualcosa di più semplice. Come sapete, recentemente mi sto appassionando al Python: e siccome la maniera migliore per fissare quello che uno impara è di metterlo per iscritto e provare a spiegarlo agli altri, oggi si parla di Python. Vi presento un piccolo esercizio in Python in cui svilupperemo le nostre abilità con la programmazione funzionale.

Supponiamo di avere un file pieno di numeri interi separati da virgole. Il file è però un pochino disordinato: su una linea ci possono essere un numero variabile di numeri, e tra un numero e l’altro e tra le virgole ci possono essere un numero variabile di spazi. Obiettivo: leggere tutti i numeri e metterli in una lista. Facile facile.

Esempio di file in input:

12 , 25, 
34, -15,    17  , 
100, 24

, 37, 99

Comciamo con il leggere tutto il file:

file = open('dati.txt', 'r')
lines = file.readlines()
all = ""
for x in lines :
    all = all + x

lines è una lista di stringhe, una per ogni linea, e con il ciclo le mettiamo tutte insieme.
Poi le splittiamo e infine le trasformiamo in interi:

nums = all.split(',')
intnum = []
for x in nums : 
    intnum.append(int(x))
print intnum

Insomma, facile. Ma tutti quei cicli for… non si può fare in maniera più compatta? Ovviamente si!
Ecco come. Innanzitutto, eliminiamo il primo ciclo for utilizzando la funzione read() che legge tutto in una stringa.

file = open('dati.txt', 'r')
all = file.read()

La stringa all adesso contiene tutto il file in una sola stringa. Adesso proviamo a fare lo split e a transformare tutto in numeri in un colpo solo:

intnum = map(int, all.split(','))
print intnum

La funzione map() applica la funzione passata come primo argomento, ovvero int(), a tutti gli elementi della lista passata come secondo argomento, ovvero al risultato di all.split(‘,’), e produce dunque una lista di interi.

A questo punto potremmo anche far tutto in una sola linea:

print map(int, open('dati.txt','r').read().split(','))

Alternativamente, invece della map() potete usare la list comprehension:

print [int(x) for x in open('dati.txt','r').read().split(',')]

Voilà, tutto in una linea!

Esercizio per casa: supponete di avere un file di configurazione con delle “proprietà”, ogni proprietà può avere assegnato un valore numerico. Ad esempio:

pippo = 15,
pluto = 25, paperino = 104, 
paperone = 75, qui, quo, qua

Nel file qui quo e qua non hanno alcun valore assegnato, quindi supponiamo che il vaolre di default per loro sia 0.
L’esercizio consiste nel leggere il file e produrre un dizionario {key,value}. L’output del programma sul file precedente dovrebbe essere:

{'pippo': 15, 'paperino': 104, 'pluto': 25, 'qua': 0, 'paperone': 75, 'qui': 0, 'quo': 0}

Cercate di farlo con il codice più breve e compatto possibile!

Buon divertimento! (poi posterò la mia soluzione, e non è affatto detto che la mia sarà la più “compatta”)

PS: nella prima versione di questo post, leggevo il file con readlines() solo per fare una join() successiva. In realtà basta fare read() per leggere l’intero file, e quindi ho editato la seconda parte del post.

Intro all’uso dei moduli in Python

“Da oggi usiamo solo più Python” annunciò tehBoss.
“E Octave” aggiunse subito dopo aver incrociato lo sguardo con Ron.
“E Java, naturalmente”.
“E…” :oops:

p1

OK, Python, una cosa elementare ma per chi è nuovo nuova. Il problema è che abbiamo alcune funzioni che usiamo in diversi script (a proposito, sempre per i nuovi, si dice –o almeno lo dico io– script quando si tratta di un programma piccolo e interpretato), sempre gli stessi, per esempio trovare le soluzioni a un’equazione polinomiale. Se troviamo un bug –ce ne sono sempre– dovremo modificare tutti gli script che usano quella funzione. A meno di averla messa in un modulo e usare quello.

Lo so che è una cosa semplicissima ma se uno è nuovo e la scrittura dello script non è il suo campo d’interesse, è un mezzo utile per velocizzare operazioni ripetitive.

Per semplicità usiamo Python in modo interattivo, in neretto quello dobbiamo scrivere noi.

La versione “normale” sarebbe:

: moduli $ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> KONST = 42
>>>
>>> def dimmiuno():
...     print 'uno'
...
>>> def dimmidue():
...     print 'due'
...
>>> def dimmitre():
...     print 'tre'
...
>>> print KONST
42
>>> dimmiuno()
uno
>>> dimmidue()
due
>>> dimmitre()
tre
>>>
: moduli $

Abbiamo cioè definito una variabile 3 funzioni, e poi usate.
La variabile e le tre funzioni possiamo inserirle in un file, così (modulo.py):

#modulo mooolto elementare

KONST = 42

def dimmiuno():
	print 'uno'

def dimmidue():
	print 'due'

def dimmitre():
	print 'tre'

A questo punto riapriamo Python e usiamo il modulo appena definito:

: moduli $ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import modulo
>>> print modulo.KONST
42
>>> modulo.dimmiuno()
uno
>>> modulo.dimmidue()
due
>>> modulo.dimmitre()
tre
>>> # mentre danno errore:
...
>>> print KONST
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'KONST' is not defined
>>> dimmiuno()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'dimmiuno' is not defined
>>>
: moduli $

OK? possiamo accedere agli oggetti contenuti nel modulo, indicando all’interprete che sono nel modulo (normalmente ne usiamo diversi) che li contiene.
Possiamo importare solo quello che ci serve, in questo caso non avremo più la necessità di indicare gli oggetti con il nome del modulo cui appartengono:

: moduli $ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from modulo import KONST, dimmiuno, dimmidue
>>> print KONST
42
>>> dimmiuno()
uno
>>> dimmidue()
due
>>> #ma, ovviamente:
...
>>> dimmitre()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'dimmitre' is not defined
>>>
: moduli $

Se gli oggetti da importare sono tanti c’è il modo di importarli tutti, così:

: moduli $ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from modulo import *
>>> print KONST
42
>>> dimmiuno()
uno
>>> dimmidue()
due
>>> dimmitre()
tre
>>>
: moduli $

Si può chiedere a Python quali oggetti sono presenti in un modulo, anzi quelli importati (notare la differenza):

: moduli $ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import modulo
>>> dir(modulo)
['KONST', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'dimmidue', 'dimmitre', 'dimmiuno']
>>>
: moduli $

: moduli $ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from modulo import *
>>> dir()
['KONST', '__builtins__', '__doc__', '__name__', '__package__', 'dimmidue', 'dimmitre', 'dimmiuno']
>>>
: moduli $

: moduli $ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from modulo import KONST, dimmiuno
>>> dir()
['KONST', '__builtins__', '__doc__', '__name__', '__package__', 'dimmiuno']
>>>
: moduli $

p2

OK? Largo ai giovani (cit.) 8-)
Poi però anche i giovani dovrebbero leggersi un manuale, ce ne sono tanti disponibili free on teh toobs.

Repl

repl

“C’è da fare un piccolo scriptino che gestisca queste operazioni ripetitive e noiose, vuoi?”
Cerrrto, subito!”
Python, Ruby, Octave, lo fanno tutti così:
casi1

e, sì, anche newLISP, Clojure, Hy e altri dela stessa famiglia (ma questo meglio non dirlo che poi mi guardano male):

casi2

E poi dice la Wiki:

A read–eval–print loop (REPL) is a simple, interactive computer programming environment. The term is most usually used to refer to a Lisp interactive environment, but can be applied to command line shells and similar environments for programming languages such as APL, BASIC, Clojure, F#, Factor, Haskell, J, Julia, Perl, PHP, Prolog, Python, R, Ruby, Scala, Smalltalk, Standard ML, Tcl, Javascript, et al.

Quasi-quasi ci provo

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

def help():
	print '\th\thelp'
	print '\tq\tquit'
	print '\ta\tcommand A'
	print '\tqui viene il resto dell\'help'

def cmdA():
	print 'cmd A'

def cmdB():
	print 'cmd B'

def cmdC():
	print 'cmd C'

#main
curr = -1

while True:
	curr += 1
	prompt = 'repl - {0} > '.format(curr)
	cmd = raw_input(prompt).strip()
	if len(cmd) == 0:
		help()
	if cmd == 'q':
		sys.exit(0)
	elif cmd == 'a':
		cmdA()
	elif cmd == 'b':
		cmdB()
	elif cmd == 'c':
		cmdC()
	elif cmd == 'h':
		help()
	else:
		print '???', cmd, '???'

repl0

Funziona! Facilissimo, estensibile.

Lo script è per la versione 2.x; per la 3.x non è necessaria l’indicazione di usare l’Unicode, raw_input() diventa input() e print è una funzione, quindi gli argomenti vanno tra parentesi.
L’ho scritto in Python per ragioni di standardizzazione ma è immediato codificarlo negli altri linguaggi.

E lo stesso script funziona, senza modifiche, con Windows:

repl0-w

In realtà dipende cosa saranno i comandi veri, ma è una questione secondaria.
OK?

Subito dopo mi sono detto che il prompt a colori sarebbe stato molto più bello. Avevo trattato l’argomento quando il blog era molto giovane, qui.

Ma è passato tanto tempo, chissà se… no, ecco cosa si trova su Stack Overflow.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

CSI="\x1B["
for c in range(8):
	print "{0}{1}{2}{3}prova di{4}{5} colore {6}".format(
			CSI, "1;", 30 + c, "m",CSI, "0m", 30 + c)
	#         0    1    2       3   4     5    6

rosso = "\x1B[1;31m"
normale = "\x1B[0m"

print "\nper me {0}va bene{1} così.".format(rosso, normale)

tavolacolori

Quindi allo script basta modificare la variabile prompt, così:

prompt = '\x1B[1;31mrepl - {0} >\x1B[0m '.format(curr)

ed ecco il risultato:

repl1

OK?
Sì, bellissimo ma:

  • non funziona con Windows (sarebbe possibile ma è macchinoso, vedi il link a Stack Overflow sopra);
  • hai appena finito il corso su GTK3 con Python, usiamo quello che viene anche più bello.

OK!, prossimamente, il prossimo anno.
Ah, sì, quasi dimenticavo: buone feste! :razz: nèh! :roll:

hy – nuova versione [0.9.10]

paultag
Forse qualcuno si ricorda di un post precedente, ormai vecchio di cinque mesi su una meravigliosa meraviglia, futura: l’unione di due dei migliori linguaggi di programmazione esistenti: Python e il Lisp.

t1

OK, il progetto continua, Paul ci sta lavorando (oltre a fare millemila altre cose), la documentazione è quasi completa, e sono state introdotte idee prese da Clojure (-> e ->>).

t0

Allora, lo provo, prima di subito. No, questa era l’intenzione ma sono indaffarato preso da parecchie cose non tutte bloggabili e qualcuna a uno stadio troppo embrionale per parlarne, prossimamente, forse…

OK, oggi provo hy. Parto da Docs » Quickstart.
Per chi, come me, usa Ubuntu il Python virtual environment lo trova nel Software Center.
Resta poi da installare pip (anche questo c’è nel Software Center) e quindi hy.

h0

OK!

Hy is python flavored lisp (or vice versa?)
Hy converts to python’s own abstract syntax tree, so you’ll soon start to find that all the familiar power of python is at your fingertips.
You have full access to python’s data types and standard library in hy

dice Paul. Vero. Cioè quasi, mancano ancora delle cose, come eval: come si fa a lispare senza eval? Il problema è noto: Tests for a future native-eval, prossimamente.

Quindi?
Ecco questo è il secondo post sull’argomento, sempre interlocutorio. Non so se lo userò, quando sarà più maturo. Ci sono parecchi progetti relativi a nuovi linguaggi o a implementazioni diverse di linguaggi esistenti (come questo e Clojure). Chissà… Per adesso chiudo qui che sono in ritardo, su tutto.
cuddles

GTK3 – conclusioni

logo1
OK, adesso ho finalmente esaminato tutti (quasi, quelli che mi piacciono) i componenti di GTK3. E posso usarli con Python 3.
Il tutorial che seguo ha un capitolo su Glade, non rientra nei miei interessi.
Confessione: già fatto un primo tentativo, un prototipo per un app, funziona.

Finora ero rimasto fedele a wxPython. Il problema è che continua a mancare per Python 3. In realtà esiste Phoenix ma non è finito e non si sa quale sarà il suo destino.

I frequentatori assidui del blog si saranno accorti del tour de force degli ultimi mesi, quasi un post al giorno. Adesso finisce questo su GTK3, ho altri argomenti in lista d’attesa, diversi.
Ma anche un po’ di stanchezza, bisogno di ferie ;-) in ritardo.

E poi, siccome l’esame di GTK3 era (ed è) finalizzato a una serie di piccole applicazioni penso di raccontarne qualcosa a riguardo, prossimamente.

A momenti dimenticavo: ho copiato tutto da qui: The Python GTK+ 3 Tutorial dove trovate molto altro, indici, tabelle, tutto quello che serve.

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.

Unisciti agli altri 63 follower