[Python] Python C ext: interfaccia asincrona basata sulla libreria Picoev

Alessandro Agosto the.6one6 a gmail.com
Dom 30 Maggio 2010 23:16:27 CEST


Ciao a tutti, è da un po' che stavo progettando di fare qualcosa unendo le
API di Python e la libreria Picoev (copyright 2009, Cybozu Labs, Inc.) che
ho usato per qualche progettino personale.
Stavo pensando di fare un piccolo webserver completamente in C asincrono ma
poi come da precedenti discussioni su questa ML mi sorgeva il dubbio sulla
reale utilità di un webserver asincrono senza la possibilità di creare altre
interfaccie (ad esempio verso DB) usando il ciclo ad eventi principale.

Ho quindi pensato di ripiegare facendo una interfaccia tra Picoev e Python
per poter usare quest'ultima direttamente da Python consentendo quindi di
sviluppare direttamente e senza altre estensioni in C, varie interfacce, e
senza dipendenze esterne.

Ho iniziato a progettare il tutto un po' di tempo fà ma poi ho iniziato  a
scrivere il codice effettivo verso sabato. Prima di iniziare ho cercato casi
simili e ho dato anche un occhio ai sorgenti di libev.

Quasi dimenticavo l'interfaccia python ho pensato di chiamarla Pycoev.
Per maggiori informazioni su Picoev vi segnalo questo articolo introduttivo
[1].
Sono a conoscenza del fatto che Picoev non è attivo ne maturo tanto quanto
libev ed attualmente offre supporto per epoll, kqueue e select (anche win32)
ma penso che se il progetto riesce si potrebbe pensare (proprio per la sua
semplicità) ad implementare altri metodi multiplexing e magari poi
sottometterli all'autore della libreria originale.

Sono qui, comunque non a fare pubblicità ma a chiedere aiuto per
completarla, migliorarla e risolvere qualche problemino.
Attualmente ho inserito un supporto a livello di codice per Python3 ma non
ho ancora avuto modo di provarlo con questa versione, mentre è compatibile
con Python2.6 (lo testo sulla 2.6.4).

Pycoev offre i metodi "init" e "deinit" per inizializzare e deinizializzare
la libreria, include già il tipo "Loop" che offre a sua volta i metodi
"add", "delete" e "loop_once". Altri metodi saranno aggiunti quando sarò
riuscito ad avere una versione funzionale e con questi metodi c'è tutto il
necessario per creare un nuovo loop ad eventi, aggiungere un file descriptor
al loop, cancellarlo, e eseguire un ciclo sul loop.

Purtroppo ci sono dei problemi proprio ad iniziare dal metodo loop_once
(file pyc_loop_methods.c). La funzione wrapper che dovrebbe eseguire la
funzione in Python quando c'è l'evento sul file descriptor sembra non
funzionare, ma tramite alcuni messaggi di debug ho scoperto che la funzione
in C che se ne occupa viene correttamente eseguita.

Dato che non avete ancora una idea di come siano composti i sorgenti (ho
pianificato i sorgenti nel modo -secondo me- più semplice possibile) e ho
creato su googlecode un progetto e vi lascio di seguito il link [2], se a
qualcuno interessa partecipare in qualsiasi modo non esitate a proporvi
siete tutti ben accetti, anzi, ho molto da imparare.

Nella cartella test c'è una specie di server, ovvero, per usare le
funzionalità di base ho creato una socket, settate le opzioni di
nonblocking, bind e listen, quindi tramite Pycoev si mette in attesa di un
evento READ sul fd socket. Quando riceve una richiesta dovrebbe eseguire la
funzione accept_cb che a sua volta non fà altro che accettare la richiesta e
stampare "a request from %s" % (caddr). Se questa fosse stata eseguita avrei
continuato a gestire la richiesta, ma già qui c'è il problema.

Internamente, non potendo la libreria eseguire una funzione in Python,
registro una funzione wrapper che accetta come parametro l'oggetto di tipo
Loop, che si occupa di eseguire la funzione registrata ed è questa funzione
wrapper (in puro C) ad essere registrata per l'evento. Quindi la libreria
all'evento READ chiama il wrapper che si occupa di eseguire la funzione
accept_cb.
La funzione wrapper viene chiamata effettivamente ma questa apparentemente
non riesce a chiamare la funzione di callback registrata. Un'altro problema
è che una volta che viene catturato l'evento READ questo si rigenera in
continuazione anzichè eseguire la callback solo una volta e cessare, ma
questo potrebbe dipendere da altro per ora almeno mi basterebbe che la
funzione fosse eseguita per procedere col debug.

Sò che ho parlato troppo etc etc, ma spero di aver esposto più o meno tutto
sul progetto.
PS. i guru mi perdonino per i sorgenti in python, essendo in fase di
sviluppo non mi sono curato di fare bei file leggibili, con l'obbiettivo di
essere distribuiti.

[1] http://developer.cybozu.co.jp/kazuho/2009/08/picoev-a-tiny-e.html
[2] http://code.google.com/p/pycoev/

Buona notte a tutti.

-- 
Alessandro A.
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: http://lists.python.it/pipermail/python/attachments/20100530/164540c0/attachment.htm 


Maggiori informazioni sulla lista Python