Forum: PC-Programmierung ast.literal_eval Ergebnisse jedes Mal anders


von Waldemarie Koninger (Gast)


Lesenswert?

Halli hallo,

ich habe ein dictionary in eine textfile geschrieben und mittels der 
Klasse Abstract Syntax Tree über ast.literal_eval() wieder von einem 
string in eine dictionary verwandelt.

Funktioniert in der Praxis, mit einer nicht unbedeutenden Einschränkung. 
Jedes Mal, wenn das Programm läuft, wird das neu eingelesene dictionary 
in einer anderen Reihenfolge ausgegeben, was eher suboptimal ist. Weiß 
jemand warum?
1
str_content = fh.read()
2
dct_content = ast.literal_eval(str_content)
3
for k1,v1 in dct_content.items():
4
  print(k1,':',v1)

von Andreas S. (motlib)


Lesenswert?

Ich nehme mal an, dass es um Python geht ..

Python dictionaries garantieren von Natur aus keine Reihenfolge der 
Elemente. Wenn Du das brauchst, kannst Du collections.OrderedDict 
verwenden.

Ich weiss aber nicht, wie man das mit deinem ast.literal_eval() 
zusammenbringt.

Vielleicht kannst Du das dictionary auch in anderer Form speichern. Z.B. 
als JSON oder YAML und kommst damit weiter.

von Waldemarie (Gast)


Lesenswert?

Der frühen Stunde geschuldet habe ich vergessen, dass es sich 
tatsächlich um Python3 handelt.

Also wenn ich das richtig sehe, bezieht sich das mit den collections auf 
die zeitliche Reihenfolge der Keys in Bezug auf deren Erstellung.

"An OrderedDict is a dict that remembers the order that keys were first 
inserted"

Was mich ganz praktisch interessiert sind aber die Values und hier der 
absolute (int) Wert.

Das Ganze wird daher auch mit einer dict-comprehension neu abgebildet, 
um das zu bezwecken. Hierbei viel mir dann aber besagter Sachverhalt 
auf, dass schon das abzubildende Dict jedes Mal anders aussah.

In den Docs steht "It is best to think of a dictionary as an unordered 
set of key: value pairs", heisst doch im Endeffekt, egal ob ich das über 
ast einlese oder direkt ein dict habe, die Reihenfolge ist immer shuffle 
oder wie?? Merkwürdig, sehr merkwürdig.

von foobar (Gast)


Lesenswert?

> die Reihenfolge ist immer shuffle oder wie?? Merkwürdig, sehr merkwürdig.

Ohne jetzt die konkreten Details von Python zu kennen, kann ich sagen, 
dass das nichts Ungewöhnliches ist.  Unordered Dictionaries werden meist 
durch Hashtables implementiert.  Zum einen wird als Hashwert gerne die 
Adresse des Keys benutzt, die von Programmlauf zu Programmlauf 
unterschiedlich sein kann (Stichwort ASLR).  Im weiteren wird gerne ein 
zusätzlicher Zufallswert mit in den Hash reingerechnet um 
Hashkollisionsangriffe zu vermeiden.  Beides führt dazu, dass ein und 
der selbe Key immer in unterschiedlichen Slots des Hashtables landet. 
Ein anschließendes Iterieren über den Hash liefert dann eine nicht 
vorhersagbare Reihenfolge der Einträge.  Diese ist nicht mal stabil - 
ein Rehashing (z.B. ein Element hinzufügen und gleich wieder löschen) 
kann zu einer total anderen Reihenfolge der exakt gleichen Elemente 
führen.

von Waldemarie (Gast)


Lesenswert?

Danke für die Erklärung(en) und die Arbeit, die mir das ganz sicher 
erspart.

Im ersten Abschnitt der offizielen Docs steht auch "... returns an 
arbitrary order..."

Nur wäre ich ehrlich gesagt nicht auf die Idee gekommen, weshalb man das 
so handhabt, aber nun gut.

Wenn man eine bestehende dictionary einliest und dann in gutem Glauben 
das Folgende macht, wenn die range bspw. 200 ist, dann Helm ab zum 
Gebet.
1
{x: 9 for x in range(100)}

popkornfaktor garantiert.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Waldemarie schrieb:
> Also wenn ich das richtig sehe, bezieht sich das mit den collections auf
> die zeitliche Reihenfolge der Keys in Bezug auf deren Erstellung.

Genau. Und auch wenn du die Elemente mit einem Iterable initialisierst,
bleiben die Elemente in der vorgegebenen Reihenfolge. Eigentlich hätte
ich gedacht, dass ein OrderedDict genau das ist, was dein Problem löst.

> Was mich ganz praktisch interessiert sind aber die Values und hier der
> absolute (int) Wert.

Diesen Satz habe ich nicht verstanden. Ist er als Begründung gedacht,
warum du kein OrderedDict verwenden möchtest?

Ab Python 3.6 sind übrigens auch die normalen Dictionaries "insertion-
ordered", und es ist offiziell entschieden worden, diese Eigenschaft in
die Sprachspezifikation aufzunehmen, d.h. sie ist auch für zukünftige
Python-Versionen garantiert. Du solltest dieses Feature aber nur nutzen,
wenn dein Code nicht auf älteren Versionen lauffähig sein muss. Also
wohl besser nicht, da du offensichtlich selber noch eine ältere Version
benutzt.

Waldemarie schrieb:
> Wenn man eine bestehende dictionary einliest und dann in gutem Glauben
> das Folgende macht, wenn die range bspw. 200 ist, dann Helm ab zum
> Gebet.
> {x: 9 for x in range(100)}
>
> popkornfaktor garantiert.

Auch das habe ich nicht verstanden. Vielleicht bin ich auch einfach noch
nicht ganz wach :)

von Sven B. (scummos)


Lesenswert?

Die Verwendung des ast-Moduls hier ist fraglich. Warum machst du das so? 
Ein JSON-Parser wäre die normale Lösung.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Sven B. schrieb:
> Die Verwendung des ast-Moduls hier ist fraglich. Warum machst du das so?
> Ein JSON-Parser wäre die normale Lösung.

Das führt zum selben Problem, nur über Umwege.

Auch JSON-Objekte sind ungeordnet. Der JSON-Decoder (zumindest der aus
der Python-Standardbibliothek) erzeugt daraus ein ebenfalls ungeordnetes
Dictionary, so dass am Ende überhaupt nichts gewonnen ist.

von Sven B. (scummos)


Lesenswert?

Yalu X. schrieb:
> Sven B. schrieb:
>> Die Verwendung des ast-Moduls hier ist fraglich. Warum machst du das so?
>> Ein JSON-Parser wäre die normale Lösung.
>
> Das führt zum selben Problem, nur über Umwege.
>
> Auch JSON-Objekte sind ungeordnet. Der JSON-Decoder (zumindest der aus
> der Python-Standardbibliothek) erzeugt daraus ein ebenfalls ungeordnetes
> Dictionary, so dass am Ende überhaupt nichts gewonnen ist.

Ja, natürlich. Das ist ein davon unabhängiges Problem.

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Seit Python 3.7 sind dictionaries offiziell geordnet. Inoffiziell schon 
seit 3.6 (implementation detail).
Die Reihenfolge entspricht der Erstellung eines Keys (insertion order). 
Wenn Writer und Reader (JSON, CSV, usw) diese Reihenfolge nicht selbst 
verändern, dann kommt am Ende dasselbe raus.
So oder so gibt es keinen vernünftigen Grund, sich was mit mit dem 
ast-Modul selber zu klöppeln.

Edit: Kann keine entsprechende Python Version garantiert werden, ist 
natürlich OrderedDict das Mittel der Wahl. Auch in diesem Fall sollte 
man sich die Dokumentation von Writer/Reader diesbezüglich genau 
ansehen.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.