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
Grazie mille !!!!!
ha funzionato e inoltre funziona anche con altri formati di file non solo con gli mp3.
piccola nota: dove descrivi l’opzione -e maca la chiusura del primo apice, io che sono poco esperto ci ho messo un’oretta a capire perchè non mi funzionava.
Grazie del prezioso aiuto.
Ciao
Eugenio
Caro Eugenio,
sono felice ti abbia funzionato e ti abbia fatto capire quanto è
potente Python.
Rispondo alla tua nota facendoti notare che in realtà non è vero che manca la chiusura, la sintassi di -e è strana e prende delle stringhe in questo modo:
-e ‘ “str1” “str2” ‘ (ho esagerato gli spazi)
Il problema è che tu probabilmente avrai fatto copia ed incolla e putroppo il file così come è pubblicato dà problemi perchè il font su questo blog converte gli apici in backquote!
Grazie della segnalazione però!
Ciao!
Alfredo