[Python] Consiglio per l' implementazione

enrico franchi enrico.franchi a gmail.com
Mer 17 Giu 2015 17:10:15 CEST


2015-06-17 10:35 GMT+01:00 Matteo Scarpa <matteoscarpa92 a gmail.com>:

> Sto cercando di scrivere un applicativo Android che recuperi da più
> pagine web dei dati (sono orari visualizzati come html) che visualizza
> filtrando in base alle preferenze dell utente.
>
Ok.

> Per alleggerire l applicazione ho intenzione di fare uno o più url dove l
> app scarica i file in formato json o simile.
>
I files sarebbero i files html o le preferenze dell'utente?


>  Il lato server che fa il parsing lo farei in python perché lavora meglio
> del Java con i file html ma oltre a Beautifullsoup non conosco moduli per
> questo genere di cose.
>

Allora, parliamoci chiaro. "Lavora meglio del Java con *" e'
un'affermazione sufficientemente discutibile in generale. Di solito stai su
Python per motivi come fai prima, lo trovi piu' mantenibile. Non perche'
lavora meglio con X o Y. Cioe' occasionalmente c'e' anche caso che ci siano
librerie che sono molto piu' convenienti da usare... da cui si arriva:
"lavora meglio con i file html" vuole dire tutto e niente.

Ora, dimentichiamo un secondo il pezzo "ovvio" di cui ti stai preoccupando
(ovvero il parsing). Pensiamo invece all'architettura di questo servizio.

Fondamentalmente questo e' un servizio web.
Allora tu avrai una serie di richieste che ti vengono dal device cui devi
rispondere. Bene.
Bisogna a questo punto capire se le pagine che devi parsare sono un set
finito oppure dipendono da quello che ti chiede l'utente.
Se sono un set finito (e dimensionato ragionevolmente), puoi pensare di
parsarle offline (batch) e ficcare i dati da qualche parte. Sempre se questi
sono ragionevolmente piccoli, sei veramente fortunato. Sebbene non sia
l'architettura ideale, puoi tranquillamente uscirtene con qualcosa di
veramente semplice, tipo un set di cron che fanno il lavoro, ti popolano un
qualche tipo di db e il tuo web service (Django-based?) legge la roba da
questo db e siamo tutti contenti.

Ora, puo' *comunque* valere la pena di mettere su Celery (o qualcosa del
genere) per farti da scheduler. In generale ti da delle decenti soluzioni
di monitoraggio del tuo servizio senza le quali non puoi nemmeno pensare di
andare in produzione. Celery ti porta a meta' strada. Se fai a mano (come
sopra, devi fartele tu con i cron).

Ma io temo che questo non sia quello che devi fare. Io temo che quello che
tu vuoi fare sia dinamicamente succhiarti la pagina su base di quello che
ha richiesto l'utente, parsarla e cacargli indietro il json. Bene: sei
sfortunato. Questa e' esattamente una cosa che Python fa *di merda*, a meno
di non spostare la tua soluzione a livello architetturale.

Ora, perche' non puo' davvero funzionare (a meno di non dovere servire 3
richieste al giorno)?

Una parte del tuo workflow e' I/O bound (leggere la richiesta dell'utente,
ottenere la pagina da un servizio remoto -- che puo' non rispondere,
rispondere in ritardo e compagnia -- e poi dare indietro la risposta) e una
parte e' CPU bound (parsare la pagina). Ah, il tutto puo' diventare molto
divertente perche' Python a volte non rilascia memoria bene quanto
dovrebbe, quindi avere un servizio che si succhia tonnellate di html e
costruisce tonnellate di json in risposta non e' esattamente salubre. Si,
di solito si dice al tuo app server di lasciare morire i worker dopo un po'
di richieste: ma e' una pezza, non e' una soluzione.

Ora l'unica possibile soluzione sensata per questo problema e' una qualche
declinazione di:
1. ricevi la richiesta
2. la ficchi in un qualche sistema di code
3. un qualche sistema di worker processa -- parsa -- e mette la risposta da
qualche parte
4. servi la risposta

Ora... se fai tutto in modo sincrono, hai tanti dei problemi della
soluzione di cui sopra. Diciamo che facendo cose sensate riesci comunque a
ridurre il problema della dicotomia fra CPU-bound e IO-bound, dovresti
anche riuscire a gestire cose come i retries (se la pagina non ti viene
servita[0]). Ovviamente hai sempre il discreto problema dei timeout (tipo
che il client tende ad incazzarsi dopo un po' che aspetta la risposta... e
allora vai di hack tipo spedire un spazio ogni tanto hurray! -- e
ovviamente non vuoi veramente tenere impegnato un worker del webserver a
spedire spazi di tanto in tanto mentre sotto processi tutto). Quindi quello
che vorresti fare e' spostarti in logica asincrona: e' anche relativamente
facile visto che possiedi sia l'app sul device che il server.

La buona notizia e' che in tutto questo Celery e' una discreta soluzione al
tuo problema di worker et similia.

La cattiva notizia e' che questo tipo di flussi si fanno davvero bene con
altre tecnologie. Tipo Go. Ma anche Java se la cava parecchio bene. Tipo...
il flusso che stiamo descrivendo sembra proprio pane per Hadoop.



--
[0] hint... se mantieni tu il servizio che hosta le pagine che devi parsare
-- cosa di cui dubito -- valuta *parecchio* la questione dei retry. Possono
causarti dolore inimmaginabile. Voglio dire... se le hostassi tu, potresti
preparare un set di API che caca direttamente il JSON.


> Ci sono alternative migliori? Sto sbagliando tutto? Esiste un modulo
> python che fa il parsing e lo esporta direttamente in json?
>
Questa domanda mi fa un po' paura... come puo' esistere un coso che
converte html in json? Mi spiego meglio... xml (e sigh, non necessariamente
html e' xml) puoi vederlo come una struttura ad albero. Il che vuole dire
che potresti certamente rappresentarla con json. Otterresti qualcosa di ben
piu' orribile, piu' grosso e meno maneggevole. Quello che tu vuoi fare, e'
estrarre specifici elementi da una pagina: e come puoi pensare che esista
un coso che esporta esattamente le cose che servono a te?

-- 
.
..: -enrico-
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20150617/1c228b28/attachment.html>


Maggiori informazioni sulla lista Python