Seite 1 von 2
Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 11:28
von Stephan_2021
Hallo,
mein Code ist:
Code: Alles auswählen
from contextlib import closing
from mysql.connector import connect
def get_data_for_grid(host, port, user, password, database, sql):
with connect(
host=host, port=port, user=user, password=password, database=database
) as connection:
with connection.cursor() as cursor:
cursor.execute(sql)
return [
tuple((str(item) if item is not None else "") for item in row)
for row in cursor.fetchall()
]
Wie kann ich die Zeile:
Code: Alles auswählen
tuple((str(item) if item is not None else "") for item in row)
so ändern/erweitern das im Falle das item eine decimal-Zahl ist der Punkt durch ein Komma ersetzt wird. Diese Umwandlung darf nicht erfolgen wenn item keine decimal-Zahl ist (z.B. also ein String der einen Punkt enthält)
Wie könnte man das erledigen?
zusätzlich:
wie kann man diese Umwandlung noch erweitern um mögliche Tausendertrenner richtig umzuwandeln?
z.B. 1,234,567.89 soll zu "1.234.567,89" werden
Gruß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 12:27
von __deets__
Indem du str durch eine Funktion ersetzt, die dein gewünschtes Verhalten produziert. Und für die deutsche Formatierung würde ich das hier einsetzen:
http://babel.pocoo.org/en/latest/api/numbers.html
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 13:05
von __blackjack__
Wobei ich da nicht nur `str()` ersetzen würde, sondern den gesamten bedingten Ausdruck, denn es soll ja nicht nur `float()` (und `decimal.Decimal`) besonders behandelt werden, sondern auch `None`. Das könnte (sollte IMHO) dann auch in der eigenen Umwandlungsfunktion verschwinden. Und bevor man da dann selbst anfängt auf Typen zu prüfen, würde ich einen Blick auf `functools.singledispatch()` werfen.
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 13:10
von Stephan_2021
Indem du str durch eine Funktion ersetzt, die dein gewünschtes Verhalten produziert.
Richtig. Und weil ich diese Funktion nicht selbst hinbekomme, habe ich den Thread hier eröffnet. Insbesondere sollen ja nicht alle "item" umgewandelt werden, sondern nur Bestimmte.
Pseudocode wäre also:
WENN "item" ungleich NULL Dann:
WENN "item" decimal ist dann format_decimal(item, locale='de')
Sonst: "item" = ""
Wie aber schreibe ich das in Python?
Gruß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 13:49
von __deets__
Und ich habe dir Hinweise gegeben, mit welchen Mitteln du zu diesem Ergebnis kommst. Die Grundlagen von Funktionen und wenn-dann-Entscheidungen musst du schon selbst mitbringen. Sie kommen ja auch in deinem Code schon vor. Warum stellen die plötzlich eine Hürde dar?
Was zum Glück vielleicht noch fehlt: typprüfung kann man mit isinstance(wert, typ) machen. __blackjack__ hat aber auch schon eine Alternative benannt.
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 13:59
von Stephan_2021
Warum stellen die plötzlich eine Hürde dar?
offen gesagt:
WEIL mir, hier im Forum, immer wieder mein eigener Code ausgeredet wird und mir anderer Code nahegelegt wird. Was ich damit meine ist das ich als Python-Anfänger zweifelsohne keinen guten Code schreibe, aber solange der Code funktioniert, sollte das doch aktzeptiert werden, aber nein, mein Code wird als unzulänglich abgetan und ich darf dann wählen ob ich notgedrungen fertigen Code nehme der mir gepostet wird oder nichts, denn wirklich eingegangen auf Nachfragen wird nur sehr begrenzt.
Deshalb ist auch der hier von mir gepostete Code nicht selbst geschrieben und ich verstehe ihn nicht in jeder Einzelheit.
Gruß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 17:18
von __deets__
Ich habe mir deine Beiträge angesehen, und dir ist hier viel und kompetent geholfen worden. Sich aus berechtigter Kritik an deinem Code ein Recht auf fertige Lösungen abzuleiten ist - genauso offen gesagt - anmaßend.
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 18:34
von Buchfink
@Stephan_2021
ich möchte mir erlauben folgendes zu sagen:
Ich persönlich finde es als Python Novize eigentlich immer ziemlich prima, wenn ich hier im Forum gleich ein "kostenloses" Code-Review mitgeliefert bekomme. Denn da muss man den Leuten, die hier helfen imho dankbar sein, dass sie sich sogar die Zeit nehmen, den Code zu optimieren.
Wenn du den gelieferten Code nicht gleich verstehst, wäre es doch vielleicht auch ein Ansatzpunkt sich mal anzusehen, was dahinter steckt.
Ich kann verstehen, dass Kritik manchmal schwer hinzunehmen ist. Aber meine Erfahrung als Entwickler ist, dass diese Art der Interaktion - nämlich "CodeReview" einem in 99% der Fälle viel mehr bringt, als vieles andere.
LG
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 19:32
von __blackjack__
Mit `singledispatch()` + Testcode für die Umwandlungsfunktion:
Code: Alles auswählen
#!/usr/bin/env python3
from contextlib import closing
from decimal import Decimal
from functools import singledispatch
import pytest
from mysql.connector import connect
@singledispatch
def convert_to_string(value):
return str(value)
@convert_to_string.register(type(None))
def _convert_none(_value):
return ""
@convert_to_string.register(float)
@convert_to_string.register(Decimal)
def _convert_number(value):
return format(value, ".2f").replace(".", ",")
def get_data_for_grid(host, port, user, password, database, sql):
with closing(
connect(
host=host,
port=port,
user=user,
password=password,
database=database,
)
) as connection:
with closing(connection.cursor()) as cursor:
cursor.execute(sql)
return [
tuple(map(convert_to_string, row)) for row in cursor.fetchall()
]
@pytest.mark.parametrize(
"value, expected",
[
("test", "test"),
(None, ""),
(42, "42"),
(2.3, "2,30"),
(Decimal("4.2"), "4,20"),
],
)
def test_convert_to_string(value, expected):
assert convert_to_string(value) == expected
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 20:44
von __deets__
Da fehlen aber noch die 1000er-Punkte. Darum würde ich da Babel nehmen.
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 20:52
von rogerb
@__deets__,
kann es bei einen Datenbankabfrage überhaupt verschiedenen Zahlenformate geben? Als Zeichenkette wäre zwar alles möglich, aber wieso sollten Dezimalzahlen als Zeichenketten abgelegt werden.
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 23:47
von Stephan_2021
Wenn du den gelieferten Code nicht gleich verstehst, wäre es doch vielleicht auch ein Ansatzpunkt sich mal anzusehen, was dahinter steckt.
Genauso sehe ich das ebenfalls. Ich muss das aber quasi schrittweise tun, damit für mich die Lernkurve nicht unerklimmbar steil wird.
Ich kann verstehen, dass Kritik manchmal schwer hinzunehmen ist.
Kritik finde ich gut, denn durch Kritik kann ich mich verbessern.
Gruß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 23:52
von Stephan_2021
Mit `singledispatch()` + Testcode für die Umwandlungsfunktion:
Danke. Das muss ich jetzt erst einmal durcharbeiten.
z.B. etwas wie:
Code: Alles auswählen
with closing(connection.cursor()) as cursor:
cursor.execute(sql)
treibt mir den Schweiß auf die Stirn, denn es ist auf den ersten Blick komplett unverständlich für mich.
Gruß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Sonntag 19. September 2021, 23:58
von Stephan_2021
Als Zeichenkette wäre zwar alles möglich, aber wieso sollten Dezimalzahlen als Zeichenketten abgelegt werden.
Falls sich diese Frage
auch an mich richtet, so ist sie einfach zu beantworten: es sollen keine Zahlen als Strings abgelegt werden, sondern ich will per Starbasic in einem:
http://www.openoffice.org/api/docs/comm ... lGrid.html
Werte anzeigen und dort sind nur Strings übergebbar. Ich könnte die notwendige Umwandlung auch in Basic machen, allein ist es schneller wenn ich es gleich in Python tue. (Geschwindigkeit ist relevant, weil es um einige tausend Datensätze geht)
Gruß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Montag 20. September 2021, 07:13
von rogerb
@Stephan_2021,
die Frage war eher, warum bei der Datenbankabfrage (mit fetchall), verschiedene Zahlenformate entstehen können. Dezimalzahlen dürften ja in einem entsprechenden Datentyp in der MySQL Datenbank abgelegt sein.
Daher verstehe ich nicht, wieso du bei numerischen Datentypen Tausendertrenner erwartest. Es sei denn, diese wurden schon so als Zeichenkette in der Datenbank abgelegt.
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Montag 20. September 2021, 07:32
von Stephan_2021
die Frage war eher, warum bei der Datenbankabfrage (mit fetchall), verschiedene Zahlenformate entstehen können. Dezimalzahlen dürften ja in einem entsprechenden Datentyp in der MySQL Datenbank abgelegt sein.
Daher verstehe ich nicht, wieso du bei numerischen Datentypen Tausendertrenner erwartest. Es sei denn, diese wurden schon so als Zeichenkette in der Datenbank abgelegt.
ich bin Python-Anfänger und da ich mit dem Datenbankzugriff per Python irgendwo beginnen musste habe ich mit dem Datentyp "Text" begonnen und bin jetzt bei "decimal" auf das 'Problem' gestossen um das sich der Thread dreht. Mir fehlt bisher schlicht der Gesamtüberblick über alle Datentypen und wie sich Python diesbezüglich verhält und ob es Besonderheiten gibt ... was auch immer.
Ich habe keine Zeit mich systematisch einzuarbeiten, sondern mache das Stück für Stück, je nachdem wie bei mir die Notwendigkeit auftaucht bestimmte DAtentypen zu benutzen. Der Nächste wird wohl "date" sein.
GRuß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Montag 20. September 2021, 07:49
von rogerb
@Stephan_2021,
ich frage nach, damit du es dir vielleicht einfacher machen kannst. Es wäre zumindest interessant zu wissen was für Datentypen du von der Datenbank erwartest (nicht die Python-Datentypen).
Die SQL-Query wird ja wahrscheinlich eine Tabelle der Datenbank abfragen und die einzelnen Spalten werden wahrscheinlich verschiedene Datentypen haben. Wenn du schon vorher weißt welche das sind, kannst du die Umwandlung in Python möglicherweise einfacher gestallten. Die Frage ist also, was für Datentypen hat die SQL-Tabelle?
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Montag 20. September 2021, 08:14
von Stephan_2021
Die Frage ist also, was für Datentypen hat die SQL-Tabelle?
derzeitig (aber das ist noch nicht zwingend vollständig, denn es wir noch etliche Tabellen mehr geben) sind das die Typen (in MySQL):
TEXT
VARCHAR
INT
DECIMAL
TINYINT
DATE
Gruß
Stephan
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Montag 20. September 2021, 08:35
von __deets__
Der entscheidende Kontext hier ist, dass die Daten in libre office überführt werden. Und das bringt seine eigenen Herausforderungen mit sich.
Im konkreten Fall hier würde ich in frage stellen, dass eine Wandlung in Text überhaupt das richtige Vorgehen ist. Stattdessen sollten aus den decimals floats werden, damit die Fragen nach Formatierung in libre Office geklärt werden können.
Re: Dezimal mit Punkt in String mit Komma umwandeln
Verfasst: Montag 20. September 2021, 09:15
von Stephan_2021
Im konkreten Fall hier würde ich in frage stellen, dass eine Wandlung in Text überhaupt das richtige Vorgehen ist.
meine Antwort darauf ist: ja.
Ich hatte auch den Grund bereits erklärt, nämlich das ich die Werte per StarBasic an ein
http://www.openoffice.org/api/docs/comm ... lGrid.html übergeben muss und dort nur Text möglich ist.
Stattdessen sollten aus den decimals floats werden,
mmh...
damit die Fragen nach Formatierung in libre Office geklärt werden können.
genau das will ich, der Geschwindigkeit wegen, vermeiden, denn in LO/StarBasic läuft das alles erheblich langsamer als in Python.
Genau das (die bessere Geschwindigkeit) ist der Grund mich überhaupt mit Python zu beschäftigen, weil ich mit Basic aktuell 'am Limit' bin, weil ich große Datenmengen handhaben muss.
Gruß
Stephan