2008-10-01 8 views
4

Je crée un serveur en réseau pour un clone-bogue que j'ai écrit en python, qui accepte les utilisateurs, résout les forums, et note l'entrée du joueur. Le fichier de dictionnaire que j'utilise est de 1,8 Mo (le dictionnaire ENABLE2K), et j'en ai besoin pour être disponible pour plusieurs classes de résolution de jeu. À l'heure actuelle, je l'ai fait pour que chaque classe parcourt le fichier ligne par ligne et génère une table de hachage (tableau associatif), mais plus j'instancie de classes de solveur, plus il prend de mémoire.Meilleure façon de stocker et d'utiliser un grand fichier texte en python

Ce que je voudrais faire est importer le fichier de dictionnaire une fois et le passer à chaque instance de solveur comme ils en ont besoin. Mais quelle est la meilleure façon de faire cela? Dois-je importer le dictionnaire dans l'espace global, puis y accéder dans la classe du solveur sous la forme globals() ['dictionary']? Ou devrais-je importer le dictionnaire puis le passer en argument au constructeur de la classe? L'un est-il meilleur que l'autre? Y a-t-il une troisième option?

Répondre

10

Si vous créez un module dictionary.py contenant du code qui lit le fichier et construit un dictionnaire, ce code ne sera exécuté que la première fois qu'il est importé. Les importations supplémentaires renverront une référence à l'instance de module existante. A ce titre, vos classes peuvent:

import dictionary 

dictionary.words[whatever] 

où dictionary.py a:

words = {} 

# read file and add to 'words' 
+0

+1: En effet.Les modules sont comme des objets singleton en Python. – martineau

1

Même s'il s'agit essentiellement d'un singleton à ce stade, les arguments habituels contre les globals s'appliquent. Pour un substitut singleton pythonique, cherchez l'objet "borg".

C'est vraiment la seule différence. Une fois l'objet dictionnaire créé, vous ne liez de nouvelles références que lorsque vous le transmettez, sauf si vous effectuez explicitement une copie en profondeur. Il est logique qu'il soit construit de manière centralisée une fois et une seule fois tant que chaque instance de solveur ne nécessite pas de copie privée pour être modifiée.

0

Selon ce que votre dict contient, vous pouvez être intéressé par les modules 'shelve' ou 'anydbm'. Ils vous donnent des interfaces de type dict (juste des chaînes comme clés et objets pour 'anydbm', et des chaînes comme des clés et n'importe quel objet python comme élément pour 'shelve') mais les données sont dans un fichier DBM (gdbm, ndbm, dbhash, bsddb, en fonction de ce qui est disponible sur la plate-forme.) Vous voulez probablement toujours partager la base de données réelle entre les classes comme vous le demandez, mais cela évitera l'étape d'analyse du fichier texte ainsi que la méthode keep-it-all-in -mémoire bit.

1

Adam, rappelez-vous qu'en Python quand vous dites:

a = read_dict_from_file() 
b = a 

... vous n'êtes pas en fait copiea, et donc en utilisant plus de mémoire, vous faire simplement b une autre référence au même objet .

Donc, fondamentalement des solutions que vous proposez sera beaucoup mieux en termes d'utilisation de la mémoire. Fondamentalement, lisez dans le dictionnaire une fois, puis accrochez-vous à une référence à cela. Que vous le fassiez avec une variable globale ou que vous la transmettiez à chaque instance, ou quelque chose d'autre, vous référerez le même objet sans le dupliquer.

Lequel est le plus Pythonic? C'est une toute autre boîte de Pandore, mais voici ce que je ferais personnellement:

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.

Questions connexes