Meilleure façon de stocker et d'utiliser un fichier texte volumineux en python

StackOverflow https://stackoverflow.com/questions/158546

  •  03-07-2019
  •  | 
  •  

Question

Je crée un serveur en réseau pour un clone de boggle que j'ai écrit en python, qui accepte les utilisateurs, résout les forums et marque les entrées du joueur. Le fichier de dictionnaire que j'utilise mesure 1,8 Mo (le dictionnaire ENABLE2K) et il doit être disponible pour plusieurs classes de résolution de jeux. Pour le moment, chaque classe effectue une itération ligne par ligne dans le fichier et génère une table de hachage (tableau associatif), mais plus le nombre de classes de solveur que j'instancie est important, plus la mémoire utilisée est importante.

Ce que je voudrais faire, c'est importer le fichier de dictionnaire une fois et le transmettre à chaque instance de solveur selon leurs besoins. Mais quel est le meilleur moyen de le faire? Devrais-je importer le dictionnaire dans l'espace global, puis y accéder dans la classe de solveur en tant que globals () ['dictionnaire']? Ou devrais-je importer le dictionnaire puis le transmettre sous forme d'argument au constructeur de la classe? Est-ce que l'un d'entre eux est meilleur que l'autre? Y a-t-il une troisième option?

Était-ce utile?

La solution

Si vous créez un module dictionary.py, contenant le code qui lit le fichier et construit un dictionnaire, ce code ne sera exécuté que lors de la première importation. Les importations ultérieures renverront une référence à l'instance de module existante. En tant que tel, vos cours peuvent:

import dictionary

dictionary.words[whatever]

où dictionary.py a:

words = {}

# read file and add to 'words'

Autres conseils

Même s’il s’agit essentiellement d’un singleton à ce stade, les arguments habituels contre les globals s’appliquent. Pour remplacer un singleton-substitut pythonique, recherchez le fichier "borg" objet.

C'est vraiment la seule différence. Une fois que l'objet dictionnaire est créé, vous ne liez que les nouvelles références à mesure que vous le transmettez, sauf si vous effectuez explicitement une copie complète. Il est donc logique qu’il soit construit de manière centralisée une et une seule fois, à condition que chaque instance du solveur ne nécessite pas de copie privée pour la modification.

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

a = read_dict_from_file()
b = a

... vous ne faites pas réellement copier a , et donc utiliser plus de mémoire, vous ne faites que faire de b une autre référence au même objet.

Par conséquent, toutes les solutions que vous proposez seront bien meilleures en termes d'utilisation de la mémoire. En gros, lisez le dictionnaire une fois , puis tenez-vous-en à une référence. Que vous le fassiez avec une variable globale, ou que vous le passiez à chaque instance, ou à autre chose, vous ferez référence au même objet sans le dupliquer.

Lequel est le plus pythonique? C'est une 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.

En fonction du contenu de votre dict, les modules "shelve" ou "anydbm" pourraient vous intéresser. Ils vous donnent des interfaces de type dict (juste des chaînes en tant que clés et éléments pour 'anydbm', et des chaînes en tant que clés et tout objet python en tant qu'élément pour 'shelve'), mais les données sont en réalité dans un fichier DBM (gdbm, ndbm, dbhash, bsddb, en fonction de ce qui est disponible sur la plate-forme.) Vous voudrez probablement toujours partager la base de données réelle entre les classes comme vous le souhaitez, mais cela éviterait l’étape d’analyse du fichier texte ainsi que la conservation du tout -mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top