Seite 1 von 1
Not a number...
Verfasst: Donnerstag 6. Mai 2010, 10:52
von Käptn Haddock
Hallo!
Beim Einlesen von csv-Dateien trat in Zahlenspalten plötzlich der String 'NaN' (Not a Number) auf. Soweit so gut, die Werte sollen dann sowohl als String als auch als Float in einer Datenbank vorgehalten werden. Die Entsprechende Umwandlung mit float lieferte dann für 'NaN' den Wert 'nan', dessen Annahme die DB dann mit unfreundlichem Gemotze verweigerte. Meine Frage nun: Welchen Sinn macht dieses Verhalten?
Code: Alles auswählen
>>> print float('NaN')
nan
>>> print float('blubb')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: invalid literal for float(): blubb
Also jetzt keine Lösung wie man drum rum kommt, sondern nur Erhellung warum das Verhalten von float so ist
Grüßle Uwe
Verfasst: Donnerstag 6. Mai 2010, 11:10
von Defnull
Die Frage ist also eher, warum deine DB nicht mit NaN-floats klar kommt. Vielleicht, weil "NOT NULL" in der Spalte angegeben ist? Oder weil du vorher in strings umwandelst?
Verfasst: Donnerstag 6. Mai 2010, 11:27
von noisefloor
Hallo,
was mich zur Frage führt: In was wandelt die Python DB API den float "nan" denn um? In (SQL) "NULL"? Das wäre zumindest logisch.
@Käptn Haddock: Ansonsten müsste die ggf. nan händisch in NULL umwandeln, zumindest für für die float Spalte.
BTW: warum speicherst du den Wert 2x? Ist eigentlich Platzverschwendung in der DB...
Gruß, noisefloor
Verfasst: Donnerstag 6. Mai 2010, 12:35
von Käptn Haddock
noisefloor hat geschrieben:
BTW: warum speicherst du den Wert 2x? Ist eigentlich Platzverschwendung in der DB...
Gruß, noisefloor
Abwärtskompatibilität
Eigentlich ging es mir nur um den Sinn, warum float() neben einer Fließkommazahl oder einem Fehler auch eine Stringrückgabe liefert.
Ich hatte folgendermassen zwischen den beiden (mir bekannten) Fällen unterschieden:
val wird als float in die Datenbank (Postgres über SQLAlchemy) geschrieben. Da jedoch mit der Rückgabe 'nan' auch ein String als korrektes Ergebnis auftauchen kann(was ich nicht wusste...) entsteht korrekterweise ein Fehler. Ich frage einfach nur nach dem Sinn der String-Rückgabe von Float, die mir komisch erscheint. IMHO wäre hier eine 'NaN-Exception' besser anstatt eines extra Konstrukts für das ich extra math importieren muß.
Code: Alles auswählen
try:
if math.isnan(float(value)):
self.val = None
else:
self.val = float(value)
except:
self.val = None
Vielleicht weiß ja auch jemand was besseres....
Gruß Uwe
Verfasst: Donnerstag 6. Mai 2010, 13:23
von ms4py
Ich sehe hier kein Problem?! Liefert doch keinen String zurück, wie `Defnull` auch schon gezeigt hat.
Hier ein zusammengeschustertes Beispiel mit sqlalchemy:
http://paste.pocoo.org/show/210593/
Code: Alles auswählen
(test) C:\Users\marc\Desktop\test>python model.py
<Test('1.2' - '<type 'float'>')>
<Test('nan' - '<type 'float'>')>
Kann mir nicht vorstellen, dass Postgre in diesem Zusammenhang anders reagiert.
Verfasst: Donnerstag 6. Mai 2010, 13:24
von BlackJack
@Käptn Haddock: Wo liefert `float()` denn einen String? Defnull hat's ja schon gezeigt dass Du da etwas vom Typ `float` bekommst und nicht `str`. Der Wert "not a number" gehört halt zum Wertebereich von IEEE 754-Kodierten Fliesskommazahlen. Genau wie "unendlich" auch ein gültiger Wert ist und beides bekommst Du nicht nur über die `float()`-Funktion -- die Werte können auch bei ganz gewöhnlichen Rechenoperationen entstehen:
Code: Alles auswählen
In [419]: 1e1000 * 1e1000
Out[419]: inf
In [420]: a = 1e1000 * 1e1000
In [421]: a / a
Out[421]: nan
Verfasst: Donnerstag 6. Mai 2010, 15:02
von Käptn Haddock
Ich habs ja langsam kapiert, danke allerseits.
Trotzdem bleibt ein Fehler, dem ich weiter nachspüren werde.
Gruß Uwe
Verfasst: Donnerstag 6. Mai 2010, 16:01
von noisefloor
Hallo,
habe es gerade mal bei MySQL probiert: Bei MySQL gibt es weder nan noch inf für float-Spalten.
Generiert man zwei float, z.B. wie von BlackJack gezeigt, mit diesen Werten und versucht diese via Python in eine DB zu schreiben, gibt's einen Fehler ("check Sytnax near 'inf'").
Will man mit phpmyadmin in eine float-Feld nan oder inf einfügen, wird daraus eine 0 (also die Zahl null). Auch nicht so prall...
Gruß, noisefloor
Verfasst: Donnerstag 6. Mai 2010, 16:31
von DasIch
Wer ein kaputtes DBMS nutzt ist auch selber Schuld.
Verfasst: Donnerstag 6. Mai 2010, 16:40
von lunar
DasIch hat geschrieben:Wer ein kaputtes DBMS nutzt ist auch selber Schuld.
Hast Du noch mehr so hilfreiche Kommentare?
Verfasst: Donnerstag 6. Mai 2010, 17:04
von DasIch
lunar hat geschrieben:Hast Du noch mehr so hilfreiche Kommentare?
Sicherlich.
Verfasst: Donnerstag 6. Mai 2010, 17:10
von BlackJack
Was sagt denn der SQL-Standard zu diesen Werten? Sind "NaN" und "unendlich" da überhaupt vorgesehen?
Verfasst: Donnerstag 6. Mai 2010, 18:02
von Käptn Haddock
BlackJack hat geschrieben:Was sagt denn der SQL-Standard zu diesen Werten? Sind "NaN" und "unendlich" da überhaupt vorgesehen?
Ok, PostgreSQL kann das auch, SQLAlchemy auch. Aber die Spalte, um die es sich dreht, ist als Numeric deklariert, da geht das natürlich nicht. Leider ist nirgendwo wirklich dokumentiert, was man da so an Daten vorgeworfen kriegt.
Ich liebe sowas. Grmpf
Schön Abend noch und Danke für die Hilfe
Uwe
Verfasst: Freitag 7. Mai 2010, 10:55
von noisefloor
Hallo,
Was sagt denn der SQL-Standard zu diesen Werten? Sind "NaN" und "unendlich" da überhaupt vorgesehen?
Gute Frage. Wenn ich
diese Seite richtig deute ist sowohl NaN, +inf als auch -inf Teil der ANSI SQL Spez.
DasIch hat es etwas, äh, sagen wir mal "stark vereinfacht", formuliert, dass MySQL es mit Standards ja nicht sooo genau nimmt. Interessant ist halt die Frage, welche anderen verbreiteten relationalen DBs es unterstützen. Oracle auf jeden Fall, das findet man leicht im Netz.
Aber SQLite? Oder SQL Server?
@Käptn Haddock: Schau auch mal in den obigen Link, da ist recht ausführlich erklärt, was wo bei PostgreSQL geht.
Gruß, noisefloor
Verfasst: Samstag 8. Mai 2010, 01:20
von noisefloor
Hallo,
SQLIte verhält sich nach meinen Test so: Man kann in eine Spalte vom Typ "real" ohne Problem 'nan' oder '+inf' schreiben, SQLite speichert das ohne gemecker - aber als String, trotz des Spaltentyps "real".
Wenn man die Werte unter Python abfragt bekommt man einen Unicode-String zurück, also u'nan' oder u'+inf' - dann man dann explizit in einen float-wert wandeln müsste...
Gruß, noisefloor
Verfasst: Samstag 8. Mai 2010, 02:54
von ms4py
noisefloor hat geschrieben:Hallo,
SQLIte verhält sich nach meinen Test so: Man kann in eine Spalte vom Typ "real" ohne Problem 'nan' oder '+inf' schreiben, SQLite speichert das ohne gemecker - aber als String, trotz des Spaltentyps "real".
Wenn man die Werte unter Python abfragt bekommt man einen Unicode-String zurück, also u'nan' oder u'+inf' - dann man dann explizit in einen float-wert wandeln müsste...
Gruß, noisefloor
Deshalb sqlalchemy, damit funktioniert es problemlos, s. oben

Verfasst: Samstag 8. Mai 2010, 11:53
von noisefloor
Hallo,
@ms4py: Ja ja...
Zwei Fragen, weil ich kein SQAlchemy habe / nutze:
1. SQLite akzeptiert als Varianten von nan, also 'nan', 'Nan', 'nAn' usw. - kommt SQAlchemy damit auch klar?
2. Was passiert, wenn du ein deinem Beispiel MySQL als DB-Engine nimmst?
Gruß, noisefloor
Re:
Verfasst: Montag 10. Mai 2010, 17:57
von Käptn Haddock
noisefloor hat geschrieben:
@Käptn Haddock: Schau auch mal in den obigen Link, da ist recht ausführlich erklärt, was wo bei PostgreSQL geht.
Gruß, noisefloor
Danke, die Orginal-Postgres-Doku beschreibt es auch sehr gut, man muß nur wissen nach was man suchen muß. Es funktioniert im übrigen auch mit Numeric-Feldern

.
Meist werden die Bezeichnungen case-insensitive behandelt, jedenfalls war das bisher bei allem was ich in der letzten Zeit darüber so gelesen habe. Insofern könnte man meinen, das MySQL das auch so macht.
Gruß Uwe