Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Auto-intern()

6 réponses
Avatar
Alain Ketterlin
Salut,

J'ai un script qui manipule de tr=C3=A8s gros dictionnaires, lus dans un
fichier et reconstruits =C3=A0 l'aide de eval(). Il y a l=C3=A0-dedans plei=
n de
cha=C3=AEnes de caract=C3=A8res, avec beaucoup de r=C3=A9p=C3=A9tition.

Malheureusement, la m=C3=A9moire utilis=C3=A9e s'envole (plus de 6 giga ave=
c 200
ou 300 mega de texte original). Y a-t-il une possibilit=C3=A9 que les cha=
=C3=AEnes
soient automatiquement pass=C3=A9es =C3=A0 intern() ? Ou bien dois-je le fa=
ire =C3=A0
la main ?

Merci d'avance.

-- Alain.

6 réponses

Avatar
Alain BARTHE
Alain Ketterlin a écrit :
Salut,

J'ai un script qui manipule de très gros dictionnaires, lus dans un
fichier et reconstruits à l'aide de eval(). Il y a là-dedans plein de
chaînes de caractères, avec beaucoup de répétition.

Malheureusement, la mémoire utilisée s'envole (plus de 6 giga avec 200
ou 300 mega de texte original). Y a-t-il une possibilité que les chaînes
soient automatiquement passées à intern() ? Ou bien dois-je le faire à
la main ?

Merci d'avance.

-- Alain.



Pourquoi le eval() ?

Je ferais plutôt :
- Lire dans le fichier cle + valeur puis
- dico [cle] = valeur


D'où vient le fichier texte ?
S'il est géré par un appli Python (ou autre), tu gagnerais peut être à
utiliser sqllite : moins de données en mémoire, les clés gérées par
l'index, etc...

Il faudrait un peu plus d'infos pour répondre au problème.
Avatar
Alain Ketterlin
Alain BARTHE writes:

J'ai un script qui manipule de très gros dictionnaires, lus dans un
fichier et reconstruits à l'aide de eval(). Il y a là-dedans p lein de
chaînes de caractères, avec beaucoup de répétition.





Pourquoi le eval() ?

Je ferais plutôt :
- Lire dans le fichier cle + valeur puis
- dico [cle] = valeur



En fait, mes structures sont un peu plus compliquées qu'un seul niveau
de dictionnaire. Il y a une grosse structure de premier niveau, dans
laquelle plein de détails sont lus sous la forme de litéraux pyth on
(typiquement, à chaque fois, un dictionnaire dont les valeurs sont des
listes dont les éléments sont des arbres dont les feuilles sont d es
chaines). J'ai un parser pour la "macro" structure, et il y a plein
d'appel à eval() (en général, plusieurs milliers).

D'où vient le fichier texte ?



Généré par une appli à moi (qui n'est pas écrite e n python). Ca me sert
à debugger et parcourir des structures assez complexes, pour faire des
tas de tests annexes, des affichages, etc. L'appli principale dump ses
structures, et tout le test est reporté dans des scripts python.

S'il est géré par un appli Python (ou autre), tu gagnerais peut être à
utiliser sqllite : moins de données en mémoire, les clés g érées par
l'index, etc...



En fait, ça me poserait plus de problèmes de passer tout dans une base
relationnelle. L'avantage de la manip, c'est justement d'éviter des
transformations de structures de données.

J'ai fini par traverser le résultat de chaque eval() pour recontruire
une structure identique mais dont les chaines sont internées. J'ai gag né
un tiers en volume. Ca devrait aller pour l'instant.

-- Alain.
Avatar
Michel Claveau - MVP
Bonsoir !

Pour un truc un peu similaire, j'utilise cPickle (dump pour enregistrer, load pour charger).

@+
--
Michel Claveau
Avatar
Alain Ketterlin
Alain BARTHE writes:

Effectivement, c'est un peu plus complexe qu'indiqué dans le message
initial.


[...]

Oui, je ne voulais pas effrayer tout le monde avec mes usines à gaz.

Si le fichier était généré en python, tu aurais pu ut iliser pickle
pour dumper le dictionnaire.


[...]

J'avais essayé pickle (en fait, cPickle) il y a quelques temps et
j'étais assez déçu : ça n'allait pas plus vite qu'un pa rser écrit à la
main (ça c'est normal), et les fichiers étaient à peu prà ¨s de la même
taille (mais par défaut c'est en ASCII). Cela dit, je n'avais pas pous sé
bien loin. Je réessaierai un de ces jours et je vous tiendrai au
courant.

Pour en revenir à ma question originale (l'utilisation plus ou moins
automatique de intern()), je suis tout de même surpris qu'il ne soit p as
plus facile d'utiliser ce mécanisme : puisque les chaînes sont
immuables, autant en profiter.

Bref. Merci pour les idées.

-- Alain.
Avatar
Alain Ketterlin
"Michel Claveau - MVP"
writes:

Pour un truc un peu similaire, j'utilise cPickle (dump pour
enregistrer, load pour charger).



Avec le protocole version 2, alors ? J'avais fait une expérience peu
concluante avec le protocole 0 (voir mon autre message de ce jour). Cela
dit, dans mon cas, je n'écris pas, je ne fais que lire. Et, au passage,
pickle ne parle pas de intern(), ce qui est décevant.

-- Alain.
Avatar
Antoine Pitrou
On Mon, 28 Sep 2009 15:22:06 +0200, Alain Ketterlin wrote:

Pour en revenir à ma question originale (l'utilisation plus ou moins
automatique de intern()), je suis tout de même surpris qu'il ne soit pas
plus facile d'utiliser ce mécanisme : puisque les chaînes sont
immuables, autant en profiter.



Vu sa taille, j'imagine que ton fichier est auto-généré.
Dans ce cas, tu peux explicitement appeler intern() dans ton
dictionnaire, par exemple en écrivant i('toto') au lieu de 'toto'.

Par exemple :

s = """ {i('a a'): i('b b'), i('b b'): i('c c')} """
d = eval(s, dict(i=intern))
[(id(k), id(v)) for k, v in d.items()]






[(28633200, 28633152), (28633152, 28632912)]
d = eval(s, dict(i=intern))
[(id(k), id(v)) for k, v in d.items()]






[(28633200, 28633152), (28633152, 28632912)]

Les ids sont les mêmes... Alors qu'en n'appelant pas intern() :

d = eval(s, dict(i=lambda x: x))
[(id(k), id(v)) for k, v in d.items()]






[(28632912, 28633152), (28633152, 28633200)]
d = eval(s, dict(i=lambda x: x))
[(id(k), id(v)) for k, v in d.items()]






[(28633056, 28633200), (28633200, 28632912)]

De nouvelles chaînes ont été créées et détruites.

a+

Antoine.