Il modo migliore per archiviare e utilizzare un grande file di testo in Python
Domanda
Sto creando un server in rete per un clone di boggle che ho scritto in Python, che accetta gli utenti, risolve le schede e segna l'input del giocatore. Il file del dizionario che sto usando è 1,8 MB (il dizionario ENABLE2K) e ho bisogno che sia disponibile per diverse classi di risolutore di giochi. In questo momento, ce l'ho in modo che ogni classe esegua l'iterazione del file riga per riga e generi una tabella hash (array associativo), ma più classi di risolutore ho istanza, più memoria occupa.
Quello che vorrei fare è importare il file del dizionario una volta e passarlo a ogni istanza del risolutore quando ne hanno bisogno. Ma qual è il modo migliore per farlo? Devo importare il dizionario nello spazio globale, quindi accedervi nella classe del solutore come globals () ['dizionario']? O dovrei importare il dizionario e poi passarlo come argomento al costruttore della classe? Uno di questi è migliore dell'altro? C'è una terza opzione?
Soluzione
Se si crea un modulo Dictionary.py, contenente il codice che legge il file e crea un dizionario, questo codice verrà eseguito solo la prima volta che viene importato. Ulteriori importazioni restituiranno un riferimento all'istanza del modulo esistente. Pertanto, le tue lezioni possono:
import dictionary
dictionary.words[whatever]
dove dizionario.py ha:
words = {}
# read file and add to 'words'
Altri suggerimenti
Anche se è essenzialmente un singleton a questo punto, si applicano i soliti argomenti contro i globali. Per un sostituto singleton pitone, cerca il " borg " oggetto.
Questa è davvero l'unica differenza. Una volta creato l'oggetto dizionario, si vincolano solo nuovi riferimenti mentre lo si passa a meno che non si esegua esplicitamente una copia profonda. Ha senso che sia costruito centralmente una volta e una sola volta, purché ogni istanza del solutore non richieda una copia privata per la modifica.
Adam, ricordalo in Python quando dici:
a = read_dict_from_file()
b = a
... in realtà non stai copiando a
, e quindi usando più memoria, stai semplicemente facendo b
un altro riferimento allo stesso oggetto.
Quindi sostanzialmente qualsiasi delle soluzioni che proporrete sarà molto meglio in termini di utilizzo della memoria. Fondamentalmente, leggi nel dizionario una volta e poi aggrappati a un riferimento a quello. Che tu lo faccia con una variabile globale, o lo passi a ciascuna istanza o qualcos'altro, farai riferimento allo stesso oggetto e non lo duplicherai.
Qual è il più Pythonic? Questa è un'intera lattina di worm, ma ecco cosa farei personalmente:
def main(args):
run_initialization_stuff()
dictionary = read_dictionary_from_file()
solvers = [ Solver(class=x, dictionary=dictionary) for x in len(number_of_solvers) ]
HTH.
A seconda di cosa contiene il tuo dict, potresti essere interessato ai moduli 'shelve' o 'anydbm'. Ti danno interfacce simili a dict (solo stringhe come chiavi ed elementi per 'anydbm', e stringhe come chiavi e qualsiasi oggetto python come elemento per 'shelve') ma i dati sono in realtà in un file DBM (gdbm, ndbm, dbhash, bsddb, a seconda di ciò che è disponibile sulla piattaforma.) Probabilmente vorrai ancora condividere il database effettivo tra le classi come stai chiedendo, ma eviterebbe il passaggio di analisi del file di testo e il mantenimento del tutto in -memory bit.