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.”

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

Mac OS X 10.5 e Record Extension

In questo articolo parlerò della Record Extension. Drizzate bene le antenne perchè questa cosa probabilmente non la sanno in molti. Innanzitutto bisogna chiedersi “Cos’è la Record Extension?”

La record extension è la libreria responsabile della cattura degli eventi di tastiera e mouse su server X. E’ molto importante in quanto entra in gioco in diverse applicazioni per svolgere delle funzioni che non possono essere eseguite altrimenti, si pensi alla cattura di una schermata del desktop tramite snapshot. Come molti di voi sapranno Mac OS non ha un supporto nativo per il server X, o meglio ce l’ha ma bisogna installare l’ X11 o dal dvd di apple o scaricando l’ultima versione da XQuartz. Tuttavia chiunque abbia provato a lanciare un qualsiasi programma che facesse uso di queste librerie si è trovato davanti il laconico messaggio “Record Extension Not Found”.

Dopo diversi giorni di sbattimenti vari ho trovato la risposta a questo problema direttamente sulla mailing list di X11:  La record e la test extension sono state rimosse per motivi di sicurezza (per evitare ad esempio che tramite un keylogger si potesse registrare il workflow di un utente). Questa scelta implementativa però non è stata apprezzata e mi è stato assicurato che nelle prossime versioni di X11 questo problema sarà risolto inserendo un comando per abilitare/disabilitare le estensioni. Allo stato attuale è quasi pronta la rc_3 di X11 dal sito XQuartz, dove è già possibile abilitare la test extension!

Quindi non temete, tra poco rientrerete in possesso della vostra record!

Alla prossima!

Alfredo