Topic: csv.DictReader ricerca rapida valore nei record  (Letto 303 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline Patcha_it

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
csv.DictReader ricerca rapida valore nei record
« il: Giugno 08, 2018, 11:12 »
Ciao a tutti,
io sono un programmatore Java, quindi sono relativamente nuovo in python.

Devo usarlo per un ambiente dove ho limitate possibilità di testare e debuggare, quindi chiedo a voi per evitare di perdere tempo in tentativi.
Per compatibilità, devo usare per forza Python 2.7.

La mia necessità è di leggere un file csv e sto usando la classe csv.DictReader.
Per info ho preso come riferimento questa pagina: https://docs.python.org/2/library/csv.html
La mia domanda è: qual è il metodo più rapido ed ottimizzato per sapere se il csv letto contiene un determinato valore?

In pratica il csv è una lista di utenti e vari attributi relativi agli utenti.
Ed io devo verificare se un determinato utente (datomi dinamicamente dal sistema) è contenuto nel csv letto.

Nella pagina linkata sopra, l'esempio per aprire un csv dice:

import csv
with open('names.csv') as csvfile:
     reader = csv.DictReader(csvfile)
     for row in reader:
         print(row['first_name'], row['last_name'])


Sulla pagina dice genericamente che csv.DictReader genera un dict, quindi per valutare se contiene un valore, io stavo usando semplicemente qualcosa tipo:
if user in reader.values():
Dove "user" è il nome utente che mi viene dato dinamicamente dal sistema.

Ma visto poi meglio l'esempio della pagina, lui fa un ciclo for per il reader e poi legge i valori di altri dict all'interno.
Non vorrei dire una fesseria, ma a naso mi sembrerebbe una specie di contenitore di una serie di dict, o qualcosa del genere.
Quindi sono dubbioso sul fatto che usare in con reader.values() sia sufficiente.

Sapreste darmi un feedback ed eventualmente un modo per fare la verifica in modo rapido, senza dover iterare tutti i record generati dal csv.DictReader?
Tipo, la sparo lì, un "if user in reader.values().values():", nel caso sia tipo un dict di dict, potrebbe funzionare?

Spero di essermi spiegato bene... scusate ma sono newbye con i tecnicismi di python! ;)

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.851
  • Punti reputazione: 9
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #1 il: Giugno 08, 2018, 13:19 »
Mah. Guarda che facevi prima a fare la prova, sai?
Comunque, allora:

> un ambiente dove ho limitate possibilità di testare e debuggare,

Questo non ha senso. E' una cosa del tutto naturale che tu non possa "testare e debuggare", come dici tu, nel tuo ambiente di produzione. Questo però non ti impedisce di crearti un ambiente di sviluppo dove pare a te, e farci quello che vuoi. In genere quando si programma si procede in questo modo, in qualche centinaia di linguaggi e credo quindi anche in java.

> Per compatibilità, devo usare per forza Python 2.7.

E questo, nel 2018, ha sempre meno senso. Davvero, python 2 è praticamente abandonware. Ormai praticamente non ci sono più librerie che non sono ancora state portate in python 3, e quelle che non lo sono sono abandonware a loro volta... Mah, vedi tu...

> qual è il metodo più rapido ed ottimizzato per sapere se il csv letto contiene un determinato valore?

A leggere il resto del post, a me non sembra che la tua domanda sia questa. Mi sembra più che altro che stai chiedendo aiuto sull'uso di csv. Ma se la tua domanda fosse davvero questa... mah, non saprei: se vuoi davvero *solo* sapere se un file di testo contiene una cosa, allora dubito che tu possa trovare un metodo più veloce di una semplice iterazione lungo le righe del file:

with open('myfile', 'r') as f:
    for line in f:
        if 'pippo' in line:
            evviva()
            break

Ora, csv certamente ti semplifica la vita con i vari dialetti possibili di un file csv, e ti offre un'api un pochino più elegante della semplice lista che avresti splittando la riga del csv. Però se quello che cerchi è la velocità pura per compiti molto semplici, allora tieni conto che l'overhead non vale la comodità in più.

Se invece (come credo di indovinare) il tuo problema è: "non capisco come si usa csv", allora boh, direi che la documentazione è piuttosto chiara. Un csv.reader rimpiazza il normale iteratore di file.open con un iteratore un pochino più fancy, ma in sostanza è la stessa minestra. In particolare, puoi iterare un csv.DictReader con un normale for, e quello ti restituisce a ogni giro un dizionario (invece della banale stringa che avresti iterando un file). Ma poi basta. Non è che ci sono magie strane tipo "un contenitore di dizionari" o quello che immagini. Così come non ci sono magie strane tipo "un contenitore di stringhe" in un oggetto file. Sono semplici iteratori python, e funzionano come semplici iteratori python (e qui però forse si pone la vera domanda...).

> il csv è una lista di utenti e vari attributi relativi agli utenti.
> devo verificare se un determinato utente è contenuto nel csv letto.

Esatto. E quindi capisci che già una cosa come if user in reader.values(), che dici tu, non ha nessun senso. A parte il fatto che non esiste proprio reader.values() (davvero, sarebbe bastato provare il codice di cui parli, invece che parlarne e basta, per capirlo), perché i "valori" di cui si parla sono quelli della *riga* del csv, non di *tutto* il csv. Quindi, sarebbe semmai if user in row.values(), seguendo l'esempio della documentazione che riporti anche tu. Ma non ha senso neppure così, o almeno non dovrebbe averlo se il tuo file csv è costruito con un minimo di criterio. Tu ti aspetti che il valore che cerchi (il nome dell'utente) non possa trovarsi in *qualsiasi* campo della riga del csv, ma appunto solo nel campo riservato al nome dell'utente (nel tuo caso il primo campo, se interpreto bene ciò che scrivi). Quindi, perché perdere tempo a cercare in *tutti* i campi?
Un DictReader ti restituisce la riga sotto forma di un dizionario le cui chiavi sono dedotte dalla prima riga del csv, oppure le fornisci tu stesso (come spiega la documentazione, del resto...). Quindi, basterà un if row['utente'] == user,  o qualunque sia il nome del campo che ti interessa. Tutto qui.

> sono newbye con i tecnicismi di python!

Eh... guarda che però questi non sono tecnicismi. Gli oggetti iterabili e for sono praticamente ovunque in python, e dove non ci sono quelli, ci sono i dizionari.

Offline Patcha_it

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #2 il: Giugno 08, 2018, 14:26 »
Il mio script di python viene implementato da un software di terze parti.
Quindi non ho controllo sulla versione di python e per farlo funzionare devo farlo girare nel software di terze parti, che ha dei componenti built in da cui derivano i dati dinamici.
Quindi non posso crearmi un ambiente di test, o usare un python più recente, perché l'unico modo di testarlo e di farlo girare correttamente è farglielo fare nel software contenitore. Su cui non ho nessun controllo.

Quindi se dico che è così per forza, fidati che può avere senso. ;)
Non sempre quando programmi per uno scopo hai il controllo su cosa usare e come.

Tornando alla domanda tecnica in sé...
Il controllo se l'utente è presente in lista mi serve proprio perché se è presente devo recuperare il resto dei dati del record del csv.
Quindi ha senso recuperare tramite la libreria che legge i csv.
Se invece non è presente, devo fare tutt'altro.

Quello che speravo di evitare è proprio l'iteratore, quindi di dover ciclare ogni volta i record sequenzialmente.
Perciò la mia domanda era "se c'è modo di farlo senza iteratore".
Visto che è un controllo preventivo che lo script fa spesso, per vari utenti, magari era meglio riuscire a non iterare il file tutte le volte.

Poiché, da quel che ho capito, python ha un sacco di metodi rapidi per concentrare operazioni complesse in brevi istruzioni magari su singola riga, la speranza è che si applicasse qualcosa anche in questo caso.
Se però mi dite che l'unica cosa utlizzabile è un'iteratore, allora mi adatto e farò una funzione a parte che itera e mi torna un boolean (così posso usare il controllo in un singolo if).

Grazie mille!
« Ultima modifica: Giugno 08, 2018, 15:59 da Patcha_it »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.851
  • Punti reputazione: 9
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #3 il: Giugno 08, 2018, 16:04 »
> Il mio script di python viene implementato da un software di terze parti.

Capisco, ma allora devi dire queste "terze parti" che sarebbe arrivato il momento di darsi una mossa.

> Quindi non posso crearmi un ambiente di test,

Uhm, direi di no, quasi per definizione (se è digitale, è riproducibile). Come minimo (e dico, come minimo), puoi farti un tuo ambiente di sviluppo (con python 2, chiaramente, e tutte le librerie significative) che lavora su dati "di prova" statici, rappresentativi di quelli che il sistema "vero" genera dinamicamente fuori da python.

> perché se è presente devo recuperare il resto dei dati del record del csv.

Sì beh, questo è quasi sempre quello che si vuole fare.

> Quindi ha senso recuperare tramite la libreria che legge i csv.

No. *Potrebbe* aver senso, ma anche no. E più descrivi il problema, meno mi sembra che abbia senso, in effetti. Il tuo problema non mi sembra legato in modo particolare al formato del file csv. Il modulo csv è un helper interessante quando hai bisogno di astrarre via la complessità delle specifiche del formato del file csv. Ma nel tuo caso... boh, a occhio direi che è indifferente usarlo. Tanto, come ti ho detto, la sua api è essenzialmente un iteratore, proprio come l'api di un normale file.

> Quello che speravo di evitare è proprio l'iteratore, quindi di dover ciclare ogni volta i record sequenzialmente.

Uhm? Stai leggendo un file di testo per estrarre un'informazione da un punto arbitrario... che altro vuoi fare, se non consumarlo sequenzialmente? Usare una bacchetta da rabdomante?
Scusa non riesco a capire che cosa non capisci. Ma ho paura di essermi fatto una serie di pre-concetti per il fatto che hai iniziato tutto questo con "sono un programmatore java"...

> Visto che è un controllo preventivo che lo script fa spesso, per vari utenti, magari era meglio riuscire a non iterare il file tutte le volte.

Capisco, certo (**). Ma allora dovrebbe convenirti leggere il file una sola volta, e "scaricare" il suo contenuto (tutto, o scartando quello che non ti serve) dentro una struttura-dati di tuo gradimento, che conservi in memoria. Ovviamente csv non può aiutarti in questo, perché non potrebbe assumere a priori quale dovrebbe essere la struttura-dati più adatta alle tue esigenze. Ma non è difficile farsela.
Poi naturalmente devi stare attento: il file csv da cui scarichi i dati, può cambiare? Se resta sempre identico, nessun problema. Ma siccome parlavi in modo un po' criptico di "dati generati dinamicamente"... Se questo csv cambia nel corso del tempo, allora forse l'unica è davvero aprirlo e ri-controllarlo ogni volta.

> da quel che ho capito, python ha un sacco di metodi rapidi per concentrare operazioni complesse in brevi istruzioni

Ehm, no. Questo sarebbe Perl, o (gulp) Php. Per fortuna Python ha un design un po' migliore.
Poi naturalmente ci sono delle *librerie* (Pandas, o va a sapere) che, nell'ambito del loro dominio applicativo, tra le molte cose che fanno possono anche leggerti un file csv e trasformartelo in una struttura-dati di un qualche tipo. Ma appunto, queste sono librerie/framework più specializzate, che presuppongono un certo utilizzo dei dati, in un certo ambito. Un linguaggio di programmazione "puro" (e la sua libreria standard) non dovrebbero essere il luogo dove inserire coltellini svizzeri di funzionalità assortite.

>  farò un metodo a parte che itera e mi torna un boolean (così posso usare il controllo in un singolo if).

Uhm, a parte che non mi è chiaro che cosa è "il controllo in un singolo if", ma è proprio quello che dovresti fare. Il bello di Python è che nove su dieci fai prima a scrivere il codice che a descrivere cosa deve fare.


_____
(**) cioè: capisco oltre una certa soglia del valore del tuo "spesso". Se al tuo sistema si connette un utente ogni due ore, allora no, non capisco.

Offline Patcha_it

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #4 il: Giugno 08, 2018, 16:36 »
Come hai detto tu, la soluzione alternativa sarebbe leggere tutto il file una tantum e metterlo all'interno di una struttura dati.
Ed è proprio per questo che pensavo l'oggetto DictReader potesse anche essere qualcosa del genere.
Poiché il sito lo dava come "metodo alternativo" introdotto con la 2.5, e c'è scritto che al contrario del metodo base questo crea un dict, pensavo fosse "alternativo" fino a questo punto.
Tipo un array di dict. O una dict contenente altri dict, se una cosa del genere è possibile. O qualcosa di simile.

Però se è comunque un reader di file, immagino vada soltanto iterato.

Per quanto riguarda ricrearsi un ambiente di test che simuli i dati che mi passerebbe il software di terze parti, allora no, faccio prima a chiedere in giro che roba è esattamente DictReader e come usarlo al meglio.
Attualmente non uso python in un ambiente di sviluppo (uso notepad++ per dircela tutta), perché non è un'attività lavorativa, ma uno script che potenzia le funzionalità di un software che uso per scopi privati.
Perciò mi costerebbe di più crearmi tutto ex-novo solo per un test, che non chiedere in un forum.

Credo però che valuterò l'opzione di farmi da solo la struttura dati, senza aspettarmi che lo faccia già la libreria csv per me.
Almeno leggo il file una volta sola.

In pratica il ciclo dello script funziona così:
- parte una sessione (del software di terze parti), che chiama un metodo che inizializza lo script, in cui creo e popolo una serie di variabili globali
- durante la sessione, viene chiamata svariate volte un'altra funzione passando dei nomi utente su cui fare o meno qualcosa in base al fatto che siano presenti nel file

In genere i file csv da leggere non dovrebbero essere troppi grandi (tipo nel mio caso), ma se condivido lo script con altra gente che utilizza quel software, loro potrebbero avere csv più corposi.

Quanto è più vantaggioso o svantaggioso leggere il file una volta sola e caricare tutti i dati in una struttura dati, in confronto a reiterare il file ogni volta?
E ancora, se l'oggetto di tipo DictReader è una variabile globale ed uso l'iteratore, rischio che ad ogni chiamata della funzione le righe già lette dall'iteratore vengano lasciate indietro, o il puntatore si riresetta ad ogni nuovo ciclo for? Devo resettarlo in qualche modo io?

PS: Ignora il fatto che ho scritto che programmo in Java. Era solo un'introduzione per far capire che non sono proprio a zero nella programmazione in generale, ma sono comunque newbye su python.
Anche io ho avuto un po' il sentore di "preconcetto" o "pregiudizio" nel tono dei tuoi post, ma mi son sforzato di ignorarlo, nel dubbio.

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.851
  • Punti reputazione: 9
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #5 il: Giugno 08, 2018, 20:05 »
> e c'è scritto che al contrario del metodo base questo crea un dict,

Non c'è scritto questo, infatti.

> Però se è comunque un reader di file, immagino vada soltanto iterato.

Infatti, sostanzialmente sì. Ripeto, csv astrae il concetto "come leggere un file in formato csv", non il concetto "che cosa me ne faccio dei dati che ci stanno dentro". La documentazione peraltro non mi sembra oscura.

> Per quanto riguarda ricrearsi un ambiente di test che simuli i dati che mi passerebbe il software di terze parti, allora no, faccio prima a chiedere in giro che roba è esattamente DictReader e come usarlo al meglio.

Sono due concetti differenti però. Un ambiente di sviluppo ben fatto ti serve a una cosa, documentarti su csv ti serve a un'altra cosa.

> Perciò mi costerebbe di più crearmi tutto ex-novo solo per un test, che non chiedere in un forum.

Cioè, in pratica il nostro tempo per risponderti vale meno del tuo tempo per farti le cose come andrebbero fatte.
Che posso dire, magari è vero. Comunque grazie anche a nome del forum.

> Credo però che valuterò l'opzione di farmi da solo la struttura dati. Almeno leggo il file una volta sola.

Come vuoi. Se dovessi scommettere un euro così alla cieca, punterei su ri-leggere il file daccapo tutte le volte. Ma valuta tu.

> Quanto è più vantaggioso o svantaggioso leggere il file una volta sola e caricare tutti i dati in una struttura dati, in confronto a reiterare il file ogni volta?

Ah, saperlo... Che cosa vuol dire "file corposo"? Ma ti sembra un termine da usare? Devi farti un'idea precisa delle metriche in gioco, devi farti dei test... ah già, ma questo forse l'avevamo già stabilito, no?
Tra l'altro, tu continui a metterla solo in termini di performance, ma francamente non saprei proprio se è la cosa più importante qui.

> uso l'iteratore, rischio che ad ogni chiamata della funzione le righe già lette dall'iteratore vengano lasciate indietro, o il puntatore si riresetta ad ogni nuovo ciclo for?

Uhm, diciamo che qui valuto che il mio tempo a spiegarti il manuale vale più del tuo tempo a leggerlo. Studiati come funziona un iteratore, e/o... fai delle prove, come già detto.

Offline Patcha_it

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #6 il: Giugno 09, 2018, 03:03 »
La documentazione dice:
- "Create an object which operates like a regular reader", laddove io ho inteso operasse come il csv.reader di base, cioè come per dire "csv.DictReader legge i dati da un file csv esattamente come lo farebbe csv.reader";
- poi dice "but maps the information read into a dict" e quindi a quel punto nella mia testa csv.DictReader poteva semplicemente creare un dict (visto che la documentazione dice "a dict" quindi uno solo, non una serie) che magari contiene i dict delle varie righe.

Per quanto mi riguarda, è fraintendibile. Se per te è chiara come il sole, allora buon per te.
Forse aiuta un tantinello il fatto che sai già come funziona, quindi sai già cosa vuole dire la documentazione.
Ovvio che col senno di poi si possa intuire meglio che la documentazione intenda dire che csv.DictReader è un normale reader (quindi itera un file) e poi le informazioni le inserisce in un dict (uno per ogni riga).
Ma se non lo sai già, secondo me quella frase è fraintendibile.


> Cioè, in pratica il nostro tempo per risponderti vale meno del tuo tempo per farti le cose come andrebbero fatte.
Questo è completamente fraintendere e rigirare quello che scrivo.

Scusami un attimo eh, ma il tono prevenuto e un po' polemico aleggiante nelle tue risposte non sta scemando, e già questo mi crea dispiacere.
Poi ora inizi a ritorcermi anche contro quel che dico... allora la cosa si fa ancora più pesante, e non posso più lasciar scorrere.
Ora spiegami un attimo. Se tutti si testassero e risolvessero i problemi ed i dubbi per conto loro, a cosa servirebbe il forum?

Nel mio caso semplicemente non ho a disposizione un ambiente di sviluppo consono a fare le varie prove, mentre esiste la rete (sai, quella cosa chiamata Internet) con dentro le community e la gente che sa già le risposte che sto cercando. Esattamente come questo forum.
Quindi, se non ti spiace, sto esattamente usando il forum per l'utilità che esso ha: per chiedere e capire qualcosa che non so.
Quindi ti pregerei di non mettermi più in bocca parole e concetti a scapito del forum, che io non ho mai espresso.

Se poi ti sta sul culo  che sono un programmatore java (e spero tanto il problema non sia questo) e pensi di dover fare una sorta di faida tipo "team python", allora sappi che inizi a razzolare male e mi troverai costretto ad iniziare a tagliare corto con i botta e risposta che mi stai dando.
Anche magari un po' il tono di supponenza con cui pretendi di sapere come gli altri possano, non possano o persino debbano fare le cose, magari si potrebbe tenere un po' a bada.
Che a tratti sembra (e qui voglio CONCEDERTI il beneficio del dubbio) che tu stia cercando di farmi passare un certo po' per idiota, in alcuni frangenti, con certe risposte.

Praticamente, renditene conto, per tutta la durata del topic ti stai concentrando più sul cazziarmi perché secondo te non utilizzo le metodologie giuste, senza neanche porti il dubbio che tu possa non conoscere tutte le realtà possibili in cui e per cui qualcuno può ritrovarsi a sviluppare python in un modo o in un altro...
Per fortuna che almeno mi hai ANCHE dato buona parte delle risposte che mi servivano. E mi sta bene almeno per quello.

Non ho bisogno che mi vieni a dire tu cosa conviene fare nel mio ambiente di sviluppo.
Questo in python per me è uno scriptarello volante, e tirarci su tutto l'ambiente di test e sviluppo sarebbe per me una perdita di tempo.
A te la cosa non piace, è un problema tuo che esula dallo scopo del topic.
Infatti non ho mai chiesto se mi convenisse tirare su tutto un ambiente di test apposta per questo, oppure se chiederlo a voi?".
Quella che hai tirato fuori è solo una tua crociata personale che stai tirando per le lunghe, e di cui sinceramente non mi frega nulla a mai me ne fregherà.

Se io avessi tirato su tutto un ambiente solo per fare sta cazzatella, avrei sprecato il mio tempo, perché non ne ho bisogno.
La scelta più saggia era chiedere dove c'era già gente che aveva le risposte.
Ed è quello che ho fatto.
Sono completamente in grado di fare questo tipo di decisione e scelte, sia che tu voglia crederci che meno.
Questa è la mia decisione e la mia convinzione e le tue fisime non me la cambieranno.

Ma, consiglio personale, prossima volta che aiuti qualcuno, per quanto ti si possa essere grati dell'aiuto, ti si sarà ancora più grati se riesci a farlo scendendo dal piedistallo ed evitando di fare tanto il giudicatore su aspetti e temi che esulano l'argomento del topic.

Sai qual era la risposta esatta al mio topic, a sto punto? Semplice:
"Non ci sono metodi brevi, perché csv.DictReader è comunque un lettore di file, quindi bisogna per forza usare l'iteratore."
Chiaro, semplice e conciso...
Senza tirare su merdoni sul perché ed il percome me lo sarei dovuto testare da solo, configurando fantomatici ambienti di sviluppo e simulando applicazioni di terze parti, quando una riga di risposta su un forum mi avrebbe già risolto tutto.

Detto questo, comunque, ti ringrazio sentitamente per il supporto e per aver trovato anche il tempo di sciogliere il mio dubbio.
Mi sei comunque stato d'aiuto, nonostante tutto.
Grazie.
« Ultima modifica: Giugno 09, 2018, 03:08 da Patcha_it »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.851
  • Punti reputazione: 9
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #7 il: Giugno 09, 2018, 08:58 »
... (e nel frattempo, nemmeno una riga di codice è ancora stata scritta e mostrata) ...

Offline riko

  • python deus
  • *
  • moderatore
  • Post: 7.453
  • Punti reputazione: 12
    • Mostra profilo
    • RiK0 Tech Temple
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #8 il: Giugno 12, 2018, 09:51 »
Sara' che e' mattina presto, ma sono davvero confuso.

Citazione
Il mio script di python viene implementato da un software di terze parti.
Quindi non ho controllo sulla versione di python e per farlo funzionare devo farlo girare nel software di terze parti, che ha dei componenti built in da cui derivano i dati dinamici.

Ok, allora lasciando stare poco rilevanti commenti su queste terze parti, non hai troppa liberta' di manovra. Stai in campana, ad un certo punto dovranno aggiornare pure loro. Tanto per sapere, di che software si parla?

Citazione
Quindi non posso crearmi un ambiente di test, o usare un python più recente, perché l'unico modo di testarlo e di farlo girare correttamente è farglielo fare nel software contenitore. Su cui non ho nessun controllo.

E su questo invece non sono molto d'accordo. Cioe', per avere un ambiente di test "perfetto", si certo hai ragione. Ma se ottenere questo ambiente e' troppo complicato (o non ne vale la pena), scrivere qualche unit-test per il codice python che scrivi e' comunque una buona idea. Vedrai che ti fara' procedere piu' spedito. Dopo tutto se l'aggeggio su cui non hai controllo chiama le tue funzioni, puoi cominciare a fare unit-test delle tue funzioni, no? Almeno qualcosa secondo me e' una buona idea.

> Come hai detto tu, la soluzione alternativa sarebbe leggere tutto il file una tantum e metterlo all'interno di una struttura dati.

Io avrei fatto questo senza passare dal via. Oggettivamente se le performance ti interessano anche in modo marginale stai confrontando un accesso O(1) in memoria con un accesso O(n) su file. Mi aspetto almeno 2 ordini di grandezza piu' lento (che poi come suggerisci altrove se il file cresce, diventano pure di piu'). E questo vale in Python come in qualunque altro linguaggio.

> Ed è proprio per questo che pensavo l'oggetto DictReader potesse anche essere qualcosa del genere.

No, non lo e'.  Potremmo discutere a lungo sul fatto che potrebbe o non potrebbe esserlo: non lo e'. Ora, evitiamo la polemica che vedo toni che si stanno accendendo e vediamo di fare qualcosa di utile.

Nota come e' scritta la documentazione: saltiamo un secondo DictReader e andiamo a leggere reader.

"""
Return a reader object which will iterate over lines in the given csvfile. csvfile can be any object which supports the iterator protocol and returns a string each time its next() method is called — file objects and list objects are both suitable.
...
Each row read from the csv file is returned as a list of strings. No automatic data type conversion is performed.
"""

Questo si legge vagamente come: "reader(file: Iterable<String>) : Reader<List<String>> (dove Reader<A> implementa anche Iterable<A>)".
Per evitare ambiguita': quel Reader li non e' eccessivamente parente di un Reader di java. E' solo un nome.

Quando in Python senti parlare di "qualcosa object", di solito si sta parlando di una "interfaccia" di convenzione (e.g., file-like object "qualunque oggetto che si comporta come un file").

Ora, una volta chiarito questo, secondo me il secondo pezzo che e' "Create an object which operates like a regular reader but maps the information read into a dict whose keys are given by the optional fieldnames parameter. " e' piuttosto chiaro. Ma quello che io penso ha poca rilevanza: e' comunque cosi', che sia chiaro o meno. Non vedo nemmeno modi ovvi per riscrivere la documentazione (altrimenti si poteva pensare di fare una patch upstream, assumendo che ci sia consenso nella community che la documentazione sia migliorata).

Purtroppo, il fatto che in Python hai duck typing rende una serie di cose che normalmente richiederebbero wrapper e layer di astrazione completamente immediate. Questo e' il lato positivo. Il lato negativo e' che questo vuole dire che la docuemntazione e' molto piu' testuale e che i tipi in generale non sono specificati esplicitamente: ti viene detto come si comporta l'oggetto che ti viene dato. Sembra una stronzata, ma e' davvero cosi' che trovi la documentazione. Vari motivi. Personalmente trovo che un paio di interfacce astratte anche solo per parlare (e.g. "object implementing File" vs. file-like object) a volte sia piu' chiaro... ma le cose vanno diversamente. Amen.

Citazione
Poiché il sito lo dava come "metodo alternativo" introdotto con la 2.5, e c'è scritto che al contrario del metodo base questo crea un dict, pensavo fosse "alternativo" fino a questo punto.
Tipo un array di dict. O una dict contenente altri dict, se una cosa del genere è possibile. O qualcosa di simile.

Ora, il punto che e' un oggetto con il comportamento che vuoi tu dovrebbe avere parametri diversi. Razionalmente, se pensiamo ad una funzione che trasforma un csv in un un oggetto su cui puoi fare ricerca O(1) per una chiave (prima colonna?) dovremmo proprio dirgli quale colonna vogliamo che sia la chiave (se no non sarebbe tanto utile) e cosa fare quando trovasse dei duplicati (li ignora silenziosamente? tiene il primo? l'ultimo? eccezione?). In generale in Python le API sono abbastanza decenti e se questa fosse la funzione, grosso modo qualche parametro sensato lo troveresti.

D'altra parte una volta che hai un reader, ti manca poco (codice non testato -- semantica, usa la colonna 0 come chiave, in caso di duplicati tieni l'ultimo):

with open(fname) as fh:
    db = {t[0]: t[1:] for t in csv.reader(fh)}

> Però se è comunque un reader di file, immagino vada soltanto iterato.

Grosso modo.

Comunque pensaci:

> Credo però che valuterò l'opzione di farmi da solo la struttura dati, senza aspettarmi che lo faccia già la libreria csv per me.

La libreria csv essenzialmente risolve il problema di "parsare" dati in formati csv; se vuoi risolvere il problema di mettere suddetti dati in una qualche struttura che renda efficienti le operazioni che mi interessano... beh, quello sta a te. Le librerie e' meglio se si focalizzano su una e una sola cosa (in questo caso, parsare e generare csv).

« Ultima modifica: Giugno 12, 2018, 09:52 da riko »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.851
  • Punti reputazione: 9
    • Mostra profilo
Re:csv.DictReader ricerca rapida valore nei record
« Risposta #9 il: Giugno 12, 2018, 15:36 »
Uhm sì, +1, tutte cose già dette e spiegate peraltro.
imho a monte il problema è che l'op non prova a *scrivere* due righe di codice invece di pianificare e girarci intorno. Dopo tutto il bello di python è proprio questo: si scrive codice in fretta, magari qualcosa di sub-ottimale ma funzionante, giusto per vedere. Poi si fa presto a migliorare.

>> Come hai detto tu, la soluzione alternativa sarebbe leggere tutto il file una tantum e metterlo all'interno di una struttura dati.
> Io avrei fatto questo senza passare dal via.

Eh sì anch'io... in situazioni comuni e sensate. Ma qui l'op ha parlato molto vagamente di cose "dinamiche", e poi non ci dice mai che cosa è in sostanza questo oggetto misterioso dentro cui il suo script dovrebbe integrarsi. A fartela breve, mi è venuta la paura che questi file csv non siano dei normali file di configurazione più o meno statici, ma vengano aggiornati dinamicamente come una specie di database dei poveri, o peggio ancora come un sistema IPC dei poveri. Ok, certo: questo sarebbe marcio fino alla radice e mi auguro davvero di sbagliami. Ma sai com'è, giusto in caso che a pensar male poi ci si azzecca, suggerivo all'op di lasciar perdere la performance e ri-aprire e leggere il file ogni volta che ce n'è bisogno.
Mah.