Don’t Panic!

Salve ragazzi,
c’è una ristretta (ma neanche tanto) cerchia di persone, che rispondono al nome di studenti universitari, che ogni mese, dopo aver sostenuto gli n-mila esami del caso, attendono con trepidazione l’uscita dei risultati.
Molti docenti pubblicano gli esiti degli esami sul loro sito, che il più delle volte è spartano ma funzionale…
Quante volte siete stati a fare “refresh” sul sito aspettando l’uscita dei risultati?
Per voi (e per me) ho creato questo semplicissimo script che controlla, ad intervalli regolari, che una pagina web sia stata aggiornata.. comodo no?
Ovviamente si può migliorare, ad esempio gestendo un log di ultime modifiche, in modo che il programma tenga lo storico!
Nota: Non funziona su siti con strutture complesse, tipo cgi based e company
Ecco il codice:

# Don't Panic! - Scritto da Alfredo Di Napoli - 2009

import urllib
import sys
import re
import time

try:
   
    sito = urllib.urlopen(sys.argv[1])
   
except IOError:
   
    print "Indirizzo non valido o irraggiungibile."
    sys.exit(1)
   
current = re.search("Last-Modified.*\r",sito.info().__str__()).group(0)
ultima_modifica = current

print "Don't Panic - v_0.1\n"
try:
   
    while current == ultima_modifica:
        exp = re.search("Last-Modified.*\r",sito.info().__str__())
        ultima_modifica = str(exp.group(0))
        print ultima_modifica
        time.sleep(10)
     
    print "C'e' stata una modifica!"   
except KeyboardInterrupt:
    print "Grazie per aver usato Don't Panic."

Spero lo troviate utile, anzi, fatemi sapere se vi ha funzionato visto che l’ho codato 

in 10 minuti e oltretutto a casa mia era andata via la corrente 😛

Usage: python dont_panic.py url_sito

Annunci

How to finally fix that damned MySQLdb module on Leopard

Ciao ragazzi,

no, non mi sono impazzito, l’articolo è in italiano 😀

Oggi voglio parlarvi di un mio esperimento portato a termine con successo. Molti di voi (spero nessuno) avranno perso il sonno nel tentare di far funzionare su leopard il modulo python MySQLdb, assolutamente indispensabile per gestire i database mysql con python, altrettanto indispensabile per usare Django.

Nota ai naviganti:  Se siete su Leopard e dovete ancora installare mysql, allora installate la versione mysql-5.0.67-osx10.4-universal.tar. gz, perchè pare che risolva i problemi di architettura. 

Cosa centra l’architettura? Il problema nasce dal fatto che è molto facile avere installata una versione di python a 32 bit, il server apache della apple a 64 bit e mysql o a 64 o a 32bit.. di conseguenza quando si prova ad importare il modulo di incappa nel seguente errore:

Traceback (most recent call last):
File “”, line 1, in
File “MySQLdb/__init__.py”, line 19, in
import _mysql
File “build/bdist.macosx-10.5-i386/egg/_mysql.py”, line 7, in
File “build/bdist.macosx-10.5-i386/egg/_mysql.py”, line 6, in __bootstrap__
ImportError: dynamic module does not define init function (init_mysql)
>>>

Ma andiamo con ordine.

Installazione e configurazione

Ci sono un sacco di guide sull’ installazione, che vi riporto come references a fine articolo, ma vediamo speditamente cosa fare. Prima di tutto scaricate il modulo dal sito ufficiale di MySQLdb, decomprimetelo ed entrate nella cartella. Per prima cosa dovete aprire il file _mysql.c e  commentare le seguenti linee:

37 //#ifndef uint 
38 //#define uint unsigned int 
39 //#endif 

dove i numeri sono i numeri di riga per una facile individuazione. Dopodichè cambiate queste altre:

484 unit port = MYSQL_PORT;

deve diventare: unsigned int port = MYSQL_PORT; 
485 unit client_flag = 0;

deve diventare: unsigned int client_flag = 0;

Bene. Ora aprite il file site.cfg e cambiate:

threadsafe = True 

in

threadsafe = False

Ora scaricatevi la versione di mysql che vi ho consigliato qualche riga fa ma NON INSTALLATELA! Piuttosto scompattatela in una cartella a vostro piacere: (es. /Users/vostrahome/mysql/).

A questo punto sempre nel file site.cfg aggiungete (o modificate se c’è) la seguente riga:

 

mysql_config = /Users/vostrahome/mysql/bin/mysql_config

dove /Users/vostrahome/mysql è la cartella dove avete decompresso la versione scaricata di mysql.

Perfetto! Adesso la procedura d’installazione dovrebbe andare per il meglio. Lanciate da shell:

python setup.py build
sudo python setup.py install

E dovrebbe filare tutto liscio. Adesso create un soft link in questo modo:

sudo ln -s /usr/local/mysql/lib/ /usr/local/mysql/lib/mysql

Poichè siamo su Mac o non su Linux. Di solito a questo punto dovreste avere una versione di MySQLdb funzionante. Per me non è stato così. Nel mio caso ha funzionato copiare la cartella lib contenuta in /Users/vostrahome/mysql dentro la mia directory di installazione di mysql, cioè /usr/local/mysql/lib/.

Per chi non fosse pratico di permessi e cose varie, prima fate un backup delle vecchie librerie :

cd /usr/local/mysql/
sudo cp -R lib lib.bak
cd lib
sudo rm *
cd ..
sudo rmdir lib
sudo cp -R /Users/vostrahome/mysql/lib /usr/local/mysql/

A questo punto se tutto è andato bene dovreste avere il vostro MySQLdb funzionante!

Ogni macchina è diversa dalle altre, quindi c’è la possibilità che la procedura che vi ho descritto possa non funzionare sui vostri computer. Per questo vi lascio dei link utili dove viene spiegato lo stesso procedimento ma con approcci diversi. Alla prossima, ciao!

Alfredo

REFERENCES:

Problems in Building 1.2.2 on Mac Os 10.5

David Cramer.net – MySQLdb on Leopard

Antonio Cangiano – How to install Django with MySQLdb on MacOSx

PyPills – Lezione 2 – Stream, parsing and many more!

Buongiorno a tutti. Oggi vi voglio parlare di come è fatto un processo. Potete immaginare un processo come una scatola nera o meglio ancora, per chi ha fatto un minimo di elettronica, come un tripolo (sennò cercate transistor su wikipedia).

Un processo nasce, cresce e muore con 3 stream “attaccati” ad esso:

Stdin, anche noto come Standard Input, è lo stream da cui il processo legge gli input provenienti dall’ esterno, tipicamente dall’ utente che l’ha lanciato o da un altro programma.

Stdout, anche noto come Standard Output, è lo stream di dati che un processo produce alla fine del suo job, volgarmente detto risultato.

Stderr, anche noto come Standard Error è lo stream in cui il programma “vomita” eventuali codici d’errore a seguito di un comportamento inaspettato.

Perchè vi dico tutto questo? Il python nasce come glue, come colla, è infatti molto usato come collante tra vari programmi. Fortunatamente per noi esiste una tecnica nota come pipelining che permette di destinare lo stdout di un processo A come stdin di un altro processo, creano cosi vere e proprie pipeline (catene di montaggio). Chi ha familiarità con il mondo Unix non si stupirà delle mie parole. Un esempio?

cat /etc/pippo.txt | wc -l

Cosa abbiamo fatto? Abbiamo letto un file con cat e abbiamo mandato lo stdout di cat in input a wc, che ci ha calcolato il numero di linee del nostro file di testo. Ma ora veniamo al python.

Su Python-it.org si era intavolata una conversazione su come fosse possibile recuperare le informazioni da un file, ad esempio come da un file MP3 fosse possibile recuperare le ID3. L’utente Flame_Alchemist, che ringrazio, ha fatto osservare che tali info, qualora presenti, risiedono nei primi 128 byte del file Mp3.

Ecco allora l’idea: sfruttiamo un tool Unix chiamato hexdump (calma Linuxofili, funziona anche da voi 😀 ) che permette di fare il dump esadecimale di qualsiasi file e poi, col nostro amato Python, ci andiamo a recuperare le informazioni che vogliamo. E’ rozzo e probabilmente non lo userete mai, l’ho scritto solo per farvi vedere due cose:

-Come sia possibile gestire il pipeline in un programma python

-Uno studio di caso di come si realizza un banale parser a partire da un dump esadecimale.

import sys

import os

class Id3Parser:

    def __init__(self):

        self.input = str.split(str.rstrip(sys.stdin.read()),"\n")

    def get_char_list(self):

        '''Ritorna il dump cosi come e' stato preso in stdin, ogni carattere

        rappresenta una cifra esadecimale'''

        return self.input

    def get_hex_list(self):

        '''Permette di ottenere una lista con il valore decimale di tutti

        i caratteri esadecimale presi da stdin'''

        hex_list = [self.hexstr2ascii(el) for el in self.input]

        return hex_list

    def get_ascii_list(self):

        '''Questa funzione preso un valore decimale ne trova il corrispettivo

        valore ascii, comprimento la lista in modo che i caratteri non ascii

        (minori di 32 in decimale) facciano da spaziatore tra un carattere

        valido e l'altro'''

        lst =[]

        prev=0

        for el in self.get_hex_list():

            if el < 32 and prev < 32:

                continue

            elif el < 32 and prev > 32:

                lst.append("00")

            else:

                lst.append(chr(el))

            prev = el

        return lst

    def hexstr2ascii(self, value):

        '''Questa funzione, preso un qualsiasi valore ascii rappresentante un

        esadecimale (es. '4B') ne trova il corrispettivo valore decimale.'''

        symbol_dict={'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,

                     '6':6,'7':7,'8':8,'9':9,

                     'A':10,'B':11,'C':12,'D':13,'E':14,'F':15}

        fst_hex = symbol_dict[value[0]]

        snd_hex = symbol_dict[value[1]]

        return (fst_hex*16 + snd_hex)

    def get_info_list(self):

        '''Questa funzione ritorna una lista delle informazioni sensibili.'''

        lst=[]

        info=""

        for el in self.get_ascii_list():

            if (el == "00"):

                lst.append(info)

                info=""

                continue

            else:

                info+=el

        return lst

if __name__ == "__main__":

    from id3parser import Id3Parser

    parser = Id3Parser()

    print parser.get_info_list()

COME SI USA:

Da shell:

$ hexdump -n 128 -v -e ‘1/1 “%02X” “\n”‘ <nome_file> | python id3parser.py

dove al posto di nome_file dovete mettere il titolo della canzone.

NOTA: Poichè il blog converte gli apici e i doppi apici in backquote, vi invito a riscrivervi tali apici se copiate ed incollate il codice nella shell, altrimenti non funziona (ringrazio Eugenio per la segnalazione).

Ci sono altri n-mila modi di farlo, mi interessava farlo così per farvi vedere come python sia un valido collante tra processi applicativi.

Vi allego come sempre il codice, alla prossima!

Alfredo Di Napoli

Codice: id3parser.py

Crittografia pure-python? Si, grazie!

Articolo scritto da Simone Ramacci “Simosito” e pubblicato prima su python-it.org e poi qui per sua gentile concessione.

 Oggi vi voglio segnalare l’implementazione pure-python di due algoritmi abbastanza celebri: Blowfish e Rijndael (per gli amici AES).

Blowfish.py

Grazie all’impegno di Ivan Voras è possibile utilizzare Blowfish per testi di lunghezza arbitraria.

Esempio (test1a.py)

import blowfish 

from hashlib import sha256

testo="Ciao, come va?" 

cipher = blowfish.Blowfish(sha256('key').digest()) 

print('Cripto')

#inizializzo CTR 

cipher.initCTR() 

ctxt=cipher.encryptCTR(testo) 

print('DeCripto') 

#idem 

cipher.initCTR() 

txt=cipher.decryptCTR(ctxt) 

print(txt)

Questo semplice codice mostra abbastanza bene l’uso di questo modulo.
È importante ricordarsi di inizializzare sempre CTR altrimenti si rimane per mesi a sbattere la testa su un errore di encoding molto antipatico.

Rijndael.py

Jeffrey Clement ci porta invece un simpatico modulo per utilizzare AES

Esempio (test2a.py)

import rijndael as r
from hashlib import sha256
key=sha256('key').digest()
testo="Ciao, come va?"
print("Cripto")
ctxt=r.EncryptData(key,testo)
print("DeCripto")
txt=r.DecryptData(key,ctxt)
print(txt)

Questo semplice codice mostra abbastanza bene l’uso di questo modulo. 
Come si può notare non c’è bisogno di nessuna inizializzazione.

Performances

Per questo test è stato usato un file di 66926 byte contenente caratteri Unicode, il Romeo e Giulietta di Bandello, che ispirò l’opera di Shakespeare.

Codifica e decodifica


 Algoritmo  real time
user time
 Blowfish 0m2.812s 0m2.804s
 Rijndael 0m10.576s  0m10.381s
 Blowfish+psyco 0m1.440s 0m1.300s
Rijndael+psyco 0m2.400s 0m2.344s

 

Codifica

 Algoritmo  real time
user time
 Blowfish 0m1.477s 0m1.416s
 Rijndael 0m5.163s 0m5.040s
 Blowfish+psyco 0m0.693s 0m0.668s
Rijndael+psyco 0m1.216s 0m1.200s

 

Il computer utilizzato per il test è un dual core 1.8 GHz con 2 Gb di RAM (24.5 % già occupato).
Nello scegliere uno dei due algoritmi si tenga presente che forniscono livelli di sicurezza differenti.”

Buon Natale a tutti!

E’ vero sono un pò in anticipo ma visto che il 25 avrò da fare vi faccio ora gli auguri! E cosa c’è di meglio di un bello scriptino?

ciao!

Alfredo

#

#BUON NATALE A TUTTI!

#

import string

class buonNatale:

def stampa_albero():

tree_base = 20

albero = "*"

print albero.center(tree_base*2)

for x in reversed(xrange(1,tree_base)):

albero+="**"

print albero.center(tree_base*2)

print "BUON NATALE A TUTTO PYTHON-IT.ORG!".center(tree_base*2)

if __name__ ==  "__main__":

stampa_albero()

C vs Python vs Java

Buongiorno a tutti.

Oggi ho fatto un esperimento. Ho implementato l’algoritmo di ordinamento più lento della storia, cioè il Selection Sort (complessità computazionale O(n^2)) , in tre diversi linguaggi: C,Python e Java. Poi ho creato un programma in Python che usando il modulo timeit cronometrasse i tempi di esecuzione dei tre diversi programmi. Il risultato? Eccolo:

C version: 0.484

Java version: 17.008

Python version: 6.657

Che il C battesse Python era scontato, ma Python batte Java alla grande: Python è il doppio più veloce del Java. Da questa prima superficiale analisi sembra che Java sia più lento del Python. Possiamo davvero ritenerci soddfisfatti? La risposta è no! Ringrazio Riovandaino del forum di Python.it.org per aver segnalato un caso in cui è Java a battare alla grande Python. Il codice lo trovate in questo post, con i relativi tempi di esecuzione. Tuttavia, come sapete, Python può, ed ecco in arrivo la scorciatoia (di scorciatoia si tratta, in effetti). La risposta è Psyco, un modulo che promette di abbattere i tempi di esecuzione degli script Python. Ma funziona davvero? Riscrivendo il codice ecco cosa otteniamo:

Pre – Psyco:

alfredo$ time python prime2.py

9592

real 0m24.237s

user 0m23.927s

sys 0m0.065s

Post – Psyco:

alfredo$ time python prime2.py

9592

real 0m1.938s

user 0m1.814s

sys 0m0.027s

Il guadagno è notevole, e il prezzo pagato? Due linee di codice all’ inizio del nostro programma.

Mica male vero?

Ringrazio tutti gli utenti di python-it.org!

Allego il codice per i più smaliziati (devo ancora riuscire a gestire bene il codice quando scrivo, la gestione di un codice in un linguaggio di programmazione in WP.com è pessima).

Alla prossima!

SpeedTest.zip

 

Alfredo

PyPills : Lezione 1 – os.system()

Buongiorno a tutti 🙂

In questo articolo inauguro un altra sezione, chiamata PyPills, cioè “Python in pillole”. Il mio obiettivo non è tanto quello di insegnare le cose base, in quanto la rete abbonda di materiale elettronico per imparare il Python, che già di per se è molto semplice. Quello che mi propongo di fare è fare luce sulle parti un pò nebulose. Una delle cose che ho più odiato nel Java era l’impossiblità di eseguire istruzioni di basso livello con un comando. Il C lo permette ma è un pò complicato lavorare sulle stringhe in quanto, come vi ricordo, per C una stringa è un array di caratteri, e come tale bisogna lavorare coi puntatori e non con gli operatori di concatenazione come il + (in C non esite per concatenare stringhe). Il python può. Questa è una frase chiave. Volete realizzare un missile per andare su marte? Python sicuramente potrà, ma potete realizzarci sicuramente un dispositivo usb per il lancio di missili (l’hanno fatto veramente). Come direbbe lo spot della Playstation 3 “Possibilità infinite” 😀 .

Tornando a noi, un comando veramente magico in Python è:

os.system(string command)

(notate che il tipo string l’ho inventato in quanto, vi ricordo, in python i tipi non vanno dichiarati esplicitamente). Cosa fa questo comando? La semplicità è potenza e viceversa, infatti questo comando esegue un comando di sistema. Quale comando? Un qualsiasi comando Unix o Dos (ma noi siamo in Unix, tant’è parleremo di questo 😛 ). Alcuni tra i più smaliziati diranno “vabbè ma non fa nulla che non si possa fare facendo uno script in bash” e ciò è sacrosanto, ma possiamo ad esempio creare il nostro bello scriptino e lanciarlo embedded all’ interno del nostro programma Python così:

import os

os.system(“./myscript.sh”)

Potente no?  Ve l’avevo detto io 😛 

Nella prossima lezione metteremo un pò da parte Python e vedremo un pò di comandi Unix molto utili, parleremo dei filtri e del pipelining.

Alla prossima!

Alfredo