Visualizza post

Questa sezione ti permette di visualizzare tutti i post inviati da questo utente. N.B: puoi vedere solo i post relativi alle aree dove hai l'accesso.


Topics - bebo

Pagine: [1]
1
Base / Dove e' meglio gestire le eccezioni?
« il: Giugno 13, 2018, 01:18 »
Ciao a tutti,
oggi ho avuto questa domanda filosofica a cui mi sono dato una mezza risposta, e su cui volevo confrontarmi con voi: in quale luogo all'interno di una libreria bisogna gestire le eccezioni?

Un po' di background, se volete, altrimenti skippate il paragrafo: per un progetto universitario sto scrivendo insieme ad alcuni colleghi una libreria (boppy) per fare simulazioni stocastiche di crescita di popolazioni; come progetto e' interessante, e ha implicato applicare ad es. shunting yard e reverse polish notation, presi in prestito da un mio vecchio progetto, in cui mi avevate gia' aiutato parecchio (in realta', dopo due anni di programmazione python ho capito che era meglio buttare quel codice e riscriverlo decentemente, ci ho messo un quarto del tempo e ora mi sento piu' confidente della robustezza e qualita' del codice); insomma, una delle cose di cui sono contento e' che adesso riusciamo a trasformare stringhe prese da un file YAML in funzioni simboliche di sympy e quindi in lambda function su cui lavorare con numpy.
Stiamo scrivendo uno script che usi la libreria, in modo da dare anche qualcosa di gia' usabile ai futuri e possibili utenti.
In particolare, questo e' lo script che stiamo producendo che va a usare la libreria che abbiamo scritto, e questo e' il file della libreria chiamato in causa; in questo caso sto passando un nome di file raccolto dall'utente ad una funzione che si occupa di aprire quel file e convertire lo YAML li' presente in un dizionario python; se il file non esiste faccio arrabbiare argparse; ma se ad esempio il file non e' YAML, catturo l'eccezione nel main.py.


TL;DR: Mentre sviluppavo l'interfaccia alla libreria qua sopra raccontata, mi sono domandato: dove dovrei gestire le eccezioni? Piu' vicino al codice che le ha alzate, o lasciarle risalire finche' qualcuno non le raccolga?

Stavo pensando che forse sarebbe meglio scremare alcuni tipi di eccezioni, ad esempio in questo caso potrei catturare l'eccezione alzata da yaml e ri-lanciare invece a mano un'eccezione ad-hoc ,parte della libreria, in modo che dall'esterno si possano catturare tutte le eccezioni sollevate dalla libreria in modo specifico, senza dover far specificare all'utente quale dipendenza (e.g., yaml) ha generato l'errore; abbiamo gia' creato un'eccezione InputError all'interno della libreria, usata nel caso l'utente inserisca un file YAML sintatticamente corretto, ma logicamente insensato (ad esempio se mancano dei componenti nel file di input (vedasi in boppy/core.py:MainController) e quindi pensavo di usarla anche in questo caso per tutto cio' che riguarda gli errori dell'utente con l'input alla libreria.
Lascerei invece andare incontrollati gli errori non-della-nostra libreria, ad es. se uno chiama la funzione filename_to_dict_converter con un file che non esiste dev'essere lui stesso a gestirsi i FileNotFoundError, IMHO. Siete d'accordo?

Mancano ancora un paio di algoritmi di simulazione in questa libreria, e poi vorrei dare un'ulteriore migliorata, tipo catchare anche le eccezioni durante il parsing (lo so, andava gia' fatto e testato, ma e' dura fare TDD  :( ), migliorare il decoupling del parsing dal resto della libreria, ed implementare un po' di algoritmi in GPU con numba o altri wrapper; poi magari vi chiedero' di darci un'occhiata ;)

2
Programmazione in rete - web / Python3.6+ - Requests asincrone
« il: Dicembre 19, 2017, 00:16 »
Buona serata ragazzi,
sto lavorando ad un progetto di analisi di crittovalute, e sto usando questa libreria (https://github.com/nlsdfnbch/bitex, ben fatta, a mio avviso.. lo sviluppatore e' in gamba, e lo sto anche aiutando a sviluppare alcune parti per rilasciare una versione 2.0) per interrogare vari exchange sui loro tassi di cambio: questa libreria funge da enorme wrapper sopra a requests, in modo da standardizzare, per quanto possibile, le diverse API delle decine di exchange disponibili.

Una chiamata di esempio e' (dopo un pip3 install --pre bitex):
>>> from bitex import Bitstamp
>>> resp = Bitstamp().ticker("btcusd")
>>> resp.json()
{'high': '19220.00', 'last': '18947.00', 'timestamp': '1513638591', 'bid': '18945.02', 'vwap': '18638.28', 'volume': '14935.03886224', 'low': '17835.20', 'ask
': '18947.00', 'open': '18953.00'}


La questione e' che ci sono parecchie di queste chiamate che vengono fatte ogni minuto per chiedere i prezzi di un centinaio di coppie, ed ovviamente vengono fatte in modo sequenziale. Finche' erano una decina, non era un grosso problema. Ma ora che sono tante, fare tante requests sequenzialmente ci mette piu' del minuto di intervallo di cui vorrei fare lo snapshot.

Cercando in rete ho trovato l'articolo di un tizio (https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html) che tentava di far scalare python ad un milione di requests/minuto usando async: ho visto il codice che ha scritto e mi e' venuto male a vedere quegli async e await sparsi in giro.
Poi ho scoperto che esiste anche la libreria grequests (requests + getenv), requests-threads (che sembra essere un one-file), requests-futures, requests con twisted.

La mia domanda e', spero, semplice e banale: su Python 3.6* su Linux, nel 2017-ormai-2018, non esiste niente per fare requests asincrone, gia' integrato in requests o facilmente ottenibile? magari un parametro da passare nei kwargs di una chiamata a requests?
Si potrebbe risolvere con un map_async da multiprocessing? o qualcosa da multithreading? o sono una BEAST practice ("problemi ora due ho", semicit. Yoda e GlennHK) ?

Salutoni

*sarei disposto ad usare anche la 3.7 in beta, se ci fossero grandi vantaggi in questo campo

3
Mondo Python / Remote package import in python: bufala?
« il: Settembre 01, 2017, 10:46 »
Avete sentito di questa?
https://lwn.net/Articles/732276/

personalmente la trovo una pessima idea. e il tizio dice di essere un security researcher (notare come il suo primo repo su github sia 'A framework for Backdoor programming!')

4
Buonasera,
sto implementando l'algoritmo DBSCAN (non la versione in pseudocodice di Wikipedia per evitare calcoli inutili) in python 2.

Ho implementato il calcolo della distanza ottimizzandola in Cython, e ora vorrei eseguirla parallelamente su piu' punti per abbattere il tempo (poi pensavo di compilare con cython anche l'algoritmo completo, ..).
So che magari python non e' lo strumento migliore per questo tipo di calcoli (mi vien voglia di imparare Go per farlo), ma e' parte di un corso di big data in python :P

Volevo quindi chiedervi quali strumenti e strategie mi consigliereste di utilizzare per eseguire piu' thread parallelamente. Vado di multiprocessing?
Se potessi lavorare con python 3 avrei usato concurrent.futures.ThreadPoolExecutor.

5
Progetti e script / Moodle2LaTeX - primo progetto personale
« il: Marzo 11, 2016, 22:48 »
Ciao a tutti!
Ho scritto recentemente un software che servisse per un prof della mia università per creare pdf per provette partendo da un database xml scaricabile dalla sua piattaforma Moodle; la scrittura mi ha preso parecchi mesi (nei quali però frequentavo lezioni, quindi c'erano settimane in cui non scrivevo manco una riga), e volevo chiedere una vostra opinione sul codice che ho scritto.
Anche grazie a una discussione qua sul forum (link) sono riuscito a sistemare una delle parti più ostiche del programma, ma che mi ha dato anche tante soddisfazioni, e per la quale vi ringrazio ancora per ciò che ho imparato.

Ho caricato il tutto pubblicamente su bitbucket, a questo indirizzo: https://bitbucket.org/moodle2latex/moodle2latex/
Per maggiori informazioni rimando al readme presente sulla pagina.

So già di aver fatto molti sbagli:
  • non ho caricato un database xml di prova, cosa che spero di sistemare nei prossimi giorni (non posso caricare i db contenenti le domande reali da esame ovviamente)
  • non ho gestito il tutto come un pacchetto, quindi non c'è modo di fare un setup tramite pip o simili: più che altro non saprei da dove cominciare, dato che alcuni pacchetti li installo di sistema (sarebbe meglio usare venv, giusto?) e alcuni tramite pip. Se avete link da cui studiare la questione, vi ringrazio.
  • il programma non è finito, mancano collegamenti tra argparse e il resto del blocco, ma le funzionalità base vanno (il progetto attualmente non serve più e quindi non ci spenderò troppo tempo ancora..)

Se avete qualche consiglio, sono tutti bene accetti! Ho sete di imparare ;)

6
Ciao a tutti!
sto cercando di usare pyparsing per calcolare il valore numerico di alcune espressioni aritmetiche (generate da moodle, e QUI c'è l'elenco delle funzioni che possono esserci e che dovrò "tradurre"), ma sto diventando matto per renderlo "universale" a tutti i tipi di espressioni.

Questi sono tutti i possibili tipi diversi di espressioni di cui devo calcolare il valore numerico:
[codice]a = "{a1}+10"
b = "{b1}*1.6*2*sqrt(2*3+1)*{b2}/{b3}"
c = "abs({c1}-{c2}*2)+3"
d = "100000000*{d1}/pi()/(pow({d2}+{d3},4)-pow({d2},4))"
e = "pow(12.32,{e1}-2+0.5*(({e1}-2.1)/abs({e1}-2.1)-1))*100*{e2}*{e3}*{e2}/{e4}/{e4}/8.854/pi()/{e5}/{e5}"
f = "pow(pow(3*8.2057*(273.15+{d1})/2/pi()/6.022/1.67/{d2}/6371,2)*{d3}*5.97,0.25)*10"[/codice]

e che dopo vorrei avere in questa forma:
[codice]ris_a = [valore_numerico_al_posto_di_a1, "+", 10]
ris_b = [valore_numerico_al_posto_di_b1, "*", 1.6, "*", 2, "*", "sqrt", [2, "*", 3, +, 1], "*", valore_numerico_al_posto_di_b2, "/", valore_numerico_al_posto_di_b3]
...[/codice]

La grammatica che ho implementato finora è questa:
[codice]from pyparsing import Word, OneOrMore, oneOf, Literal, Combine, Optional,
                ZeroOrMore, Group, Or, nums, Suppress, Forward, nestedExpr

point = Literal(".")
e = Literal("e")
integer = Word(nums)
floatnumber = Combine( integer + Optional( point + Optional(number) ) + Optional( e + integer ))
pi_symbol = Literal("pi()")
number_in_brackets = Suppress("{") + Word(lowercase).setParseAction( lambda x: 1234567890 ) + Suppress("}")
realnumber = ( integer | floatnumber | pi_symbol | number_in_brackets )

arithOp = oneOf("+ - * /")
first_kind_expr = realnumber + arithOp
second_kind_expr = arithOp + realnumber
math_expr = Optional(realnumber) + Optional(first_kind_expr) + ZeroOrMore(second_kind_expr)

function = Forward()
function << ( Word(lowercase) + Suppress("(") + Group( function | math_expr ) + Suppress(")") )

nested = Optional(Word(lowercase) + nestedExpr(content=math_expr, ignoreExpr=Literal("pi()")))
[/codice]
number_in_brackets per ora fa una semplice sostituzione numerica, ma nella realtà andrà a recuperare il valore da una lista di oggetti confrontando la stringa che coincide con la regola.


Allora, finché sono espressioni semplici come la prima, con la regola math_expr riesco a farle diventare delle istanze di pyparsing.ParseResults, e quindi in qualche modo riesco a cavarmela.

Il problema ce l'ho quando considero anche le funzioni, che si comportano similmente a normali funzioni python: nomefunzione(arg1, arg2) con numero di argomenti a seconda del tipo di funzione (si veda in cima il link all'elenco delle funzioni).
Non so come infilare anche la possibilità di avere funzioni oltre a semplici valori: ho tentato tramite la grammatica function ma appena faccio il parsing di una stringa come ad es. la e risulta: pyparsing.ParseException: Expected ")" (at char 6), (line:1, col:7)
Ho provato ad es sulla stringa c anche la funzione nestedExpr che suddivide in liste ad ogni blocco di parentesi, ma applicando la grammatica  di math_expr credo che pyparsing resti incastrato in qualche loop.


Come valutare anche le funzioni all'interno di espressioni e non solo all'inizio?

Inoltre ho alcune domande:
  • Dalla documentazione non ho ben capito quando bisogna usare ^. In particolare la frase "If two expressions match, the expression that matches the longest string will be used".
  • Perché quando bisogna utilizzare qualcosa di ricorsivo in pyparsing bisogna utilizzare l'operatore di shift binario <<? è solo un riutilizzo un po' inappropriato del simbolo di shift o sbaglio?
  • Una volta ottenuta una lista annidata, come mi consigliate di procedere? Pensavo di scorrere la lista, e ogni volta che trovo una sottolista (in realtà ancora un'istanza di pyparsing.ParseResults), "aprire" quella sottolista, scorrerla di nuovo e calcolare tutta l'espressione, ritornare al livello sopra e sostituire la sottolista con il valore appena calcolato, e via così abbassando con i vari passaggi l'altezza dell'albero astratto. Oppure lavorare con uno stack?
    Anche qua accetto consigli.

Vi ringrazio in anticipo dell'attenzione. Ovviamente ogni critica costruttiva ed ogni aiuto che vorrete darmi è molto ben accetto...
Non so dove sbattere la testa e ci ragiono da giorni.
Grazie

7
Ciao a tutti!

Mi sto imbattendo in un problemino/problemone e prima di farmi del male e perder tempo inutilmente volevo una vostra impressione o un vostro consiglio. Uso python2.7 per poter eventualmente implementare una GUI con wxPython in futuro.
Come da oggetto, ho alcuni database in formato xml in testo semplice provenienti da piattaforma moodle contenenti domande scientifiche e relative risposte da tradurre in latex. Dopo aver smanettato abbastanza con BeautifulSoup (ho dovuto inventarmi un workaround a mio avviso intelligente per leggere alcuni tag chiamati proprio <name> o <text>, si veda sotto), mi trovo di fronte a un problema: all'interno delle consegne e delle soluzioni ci sono delle formule, che devo riuscire a far interpretare a python e modificare con delle variabili che ho già però "sottomano". Magari questo mio problema non si pone perché il latex legge "nativamente" questo tipo di espressioni, ma non conoscendolo ancora appieno non so se è una stupidaggine: nel caso fermatemi.

Se avessi sbagliato sezione ditemelo pure, ma non saprei dove meglio si potrebbe collocare la discussione.

Mi spiego riportando parte del mio codice attuale e facendo un esempio.
Per ora ho scritto questo:
[codice]class question():
   """A container for all the parameters of a question in the database.

   This class accept one BeautifulSoap Tag object containing the whole
   question tags.
   """

   def __init__(self, nested_question):
      self.questiontext = nested_question.questiontext.select('text')[0].get_text().split(']]>')[0]
      self.generalfeedback = nested_question.generalfeedback.select('text')[0].get_text().split(']]>')[0]
      self.numeric_vars = [moodle_variable(var) for var in nested_question.find_all("dataset_definition")]
      #~_self.substitutor(self.questiontext)
      #~_self.substitutor(self.generalfeedback)


   def substitutor(self, text_string):
      """Grep the contents of squiggly backets and try to substitute them. """
      #~_bracket_parens = re.compile(r'{([^{}])}')
      simple_vars = re.findall(r'{(w*)}', text_string)
      for simple in simple_vars:
         for var in self.numeric_vars:
            if simple == var.name_of_var:
               print '{'+simple+'}', var.randomized
               # text_string = text_string.replace('{'+simple+'}', str(var.randomized))
               print text_string.replace('{'+simple+'}', str(var.randomized))
               break[/codice]

dove moodle_variable è la seconda classe che ho creato, ma contiene solamente il nome effettivo della variabile (che mi serve per fare il confronto qua sopra), e un valore random scelto tra il max e il min contenuti sempre nel xml.
Questo è un esempio del testo in cui potrei imbattermi, contenuto all'interno di questiontext e generalfeedback della classe question:
[codice]'blab asb {fdn} dflbsdsdf df R =  1/{f C ln[(E-V<sub>off</sub>)/(E-V<sub>on</sub>)]}= {=round(100000/{f}/{C}/log(({Vs}-{Voff})/({Vs}-{Von})))/100} kΩ ecc ecc'[/codice]
e su cui eseguirei il metodo substitutor sempre all'interno dell'init, prima su questiontext e poi su generalfeedback, all'interno dell'init (ora mi viene il dubbio che potrebbe essere una porcheria questa di eseguire un metodo dentro all'init, o no?).

Ora che ho spiegato la mia situazione, vorrei chiedere se avete qualche idea dalla quale iniziare per semplificare l'equazione precedente attraverso python.
Vorrei arrivare a concepire un algoritmo il cui risultato finale, applicato all'esempio sopra e dati f=10, C=20, Vs=30, Voff=40, Von=50, fosse una cosa del genere :
[codice]'blab asb {fdn} dflbsdsdf df R =  1/{10 30 ln[(E-V<sub>off</sub>)/(E-V<sub>on</sub>)]}= -7.21 kΩ ecc ecc'[/codice]
tralasciando il fatto che con i dati a caso che ho inserito risulta una resistenza negativa, il succo dell'algoritmo vorrei che fosse questo.



Ho usato questa regex r'{(w*)}' per selezionare le variabili singole (come {f}, {C}, {Voff}) da sostituire numericamente con i rispettivi valori (presenti nella loro istanza di moodle_variable dentro var_randomized), e in questo caso funzionerebbe per sostituire i valori con dei numeri, che per latex andrebbe benissimo, dentro al secondo blocco di parentesi graffe, quello con l'uguale.
Dopo aver eseguito questa prima "trasformazione", pensavo di utilizzare un'altra regex r'{(.*)}' per selezionare le stringhe complete "più grandi", con questo risultato:
[codice]>>> re.findall(r'{(.*?)}', x)
['fdn', 'f C ln[(E-V<sub>off</sub>)/(E-V<sub>on</sub>)]', '=round(100000/10/20/log((30-40)/(30-50)))/100'][/codice]

Ora sorgono i problemi maggiori e i dubbi:
  • attualmente usare il metodo .replace delle stringhe nel metodo substitutor non funziona. Qualcuno mi spiega come mai? dove sbaglio? centra l'unicode?
  • come distinguere le variabili come f e C all'interno del secondo blocco con le graffe della lista? Questo qui sotto cioé:
    [codice]>>> re.findall(r'{(.*?)}', x)[1]
    'f C ln[(E-V<sub>off</sub>)/(E-V<sub>on</sub>)]'[/codice]
    l'idea che mi era venuta era di splittare per spazi bianchi, in quanto dagli altri campi che ho trovato guardando nel database sembrerebbe che le variabili da sostituire siano SEMPRE separate dal resto (vedi f C ln[...). Una volta splittato andrei a confrontare ogni valore della lista con tutte le variabili contenute nella domanda e se ho fatto bingo faccio la sostituzione (però bisognerebbe sistemare il problema 1)
  • pensavo al caso limite in cui nel testo ci sia qualcosa racchiuso da graffe ma che non centra niente, non dev'essere cioè sostituito, come quel {fdn} dell'esempio. Dopo aver controllato se coincide con qualche variabile o qualche operazione matematica, dovrebbe rimanere così com'è nel testo "tradotto" finale.
  • come gestire le parentesi? cioè, come far capire a python dove inizia un'operazione e dove ne finisce un'altra? usando uno stack? e come? (mi viene in mente un esercizio sulla calcolatrice a notazione polacca inversa vista a prog1.....) Li ho studiati molto bene in C, ma in python ancora no. Eventualmente se questo fosse il caso, avreste qualche link da cui studiarli ed impararli bene?
  • dopo aver capito come gestire le parentesi dovrei creare un dizionario con la "traduzione" dei vari comandi aritmetici usati da moodle, in aritmetica di python. Qui ho trovato una lista con la spiegazione delle funzioni matematica usate da moodle (molto simili a python a dire il vero).
    In python tutto è un oggetto, giusto? Quindi si può creare un dizionario con come chiave una stringa e come valore una funzione (come math.exp()), giusto?

Sapete aiutarmi? anche solo darmi qualche dritta sarebbe oro... Ad esempio con i problemi 1 3 e 5.
E ovviamente se vorrete consigliarmi come migliorare il mio codice python lo accetto più che volentieri, sono sempre curioso e pronto ad imparare.  :py:  :birrame:

Grazie per la pazienza di aver letto questo poema.



8
Benvenuto e regolamento / Ciao a tutti :)
« il: Luglio 24, 2015, 16:20 »
Buongiorno a tutti!
Sono Alberto, studente ormai al secondo anno di Ingegneria dell'Informazione e Organizzazione d'Impresa a Trento.
Studio python con passione ormai da 2-3 anni, ma lo sto capendo meglio solo nell'ultimo anno da quando ho dato, con molto profitto, l'esame di programmazione1 basato su C e un pizzico di C++. Adoro l'informatica, ma la mia aspirazione non è di fare il programmatore tutta la vita: tra le altre cose faccio parte dello staff di fedoraonline.it, il portale italiano degli utenti di Fedora (che utilizzo esclusivamente da 7 anni ormai), e in particolare ne gestisco la documentazione nel tempo libero che riesco a dedicargli.

Sto portando avanti molti progetti, dall'imparare a scrivere GUI (cosa che mi ha sempre attirato) ad un convertitore da database xml di moodle a latex (per il quale aprirò una discussione in quanto sono "bloccato", e prima di consumare le dita vorrei qualche parere).

Per intanto, grazie di esserci, ho imparato già molto solo leggendo alcune discussioni del forum.

Buon python a tutti!  ;) :birrame:

Alberto, aka bebo_sudo

Pagine: [1]