Dezimal mit Punkt in String mit Komma umwandeln

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

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
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@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?
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

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
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

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
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der addRow Aufruf nimmt laut http://www.openoffice.org/api/docs/comm ... tml#addRow den datentyp “any” - nicht String. Das ist ein Summentyp aus diversen Typen, da sind garantiert auch floats bei. Vielleicht sogar BigDecimal. Und ich habe LibreOffice und nicht starbasic gesagt. Wenn man in Calc eine Zahl einfügt, dann formatiert es die selbst, abhängig vom locale. Zwingt man stattdessen einen String da rein, funktionieren zb Formeln auf diesen Feldern nicht mehr.
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Der addRow Aufruf nimmt laut http://www.openoffice.org/api/docs/comm ... tml#addRow den datentyp “any” - nicht String.
Dann liefere bitte einen Code, der alle Einträge richtig für ein deutsch lokalisiertes System anzeigt (wohlgemerkt kommen ja verschiedene Datentypen vor). Mir ist dass mit 15 Jahren StarBasic-Erfahrung noch nicht gelungen, aber ich lerne gerne dazu.
Wenn man in Calc eine Zahl einfügt, dann formatiert es die selbst, abhängig vom locale.
Meine Frage hatte mit Calc absolut garnichts zu tun.



EOT ... denn ich habe keine Lust weiterhin Deine und meine Zeit mit Diskussion zu vergeuden die mich einer Lösung nicht näher bringt.


Stephan
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Stephan_2021: da niemand hier Dein vollumfängliches Problem kennt, kann man auch schlecht helfen. Und wenn Du keine Lust hast, hier Dein Problem so zu beschreiben, dass wir es verstehen, dann können wir auch nicht konkret helfen.
Dazu bräuchte es erst einmal ein komplett lauffähiges Beispiel
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Sirius3 hat geschrieben: Montag 20. September 2021, 15:21 @Stephan_2021: da niemand hier Dein vollumfängliches Problem kennt, kann man auch schlecht helfen. Und wenn Du keine Lust hast, hier Dein Problem so zu beschreiben, dass wir es verstehen, dann können wir auch nicht konkret helfen.
Dazu bräuchte es erst einmal ein komplett lauffähiges Beispiel
Entschuldigung, aber das stimmt doch nicht. Mein Problem hatte ich vollständig beschrieben, denn es geht nur darum wie ich bei einer bestehenden und funktionierenden Python-Funktion das Ergebnis, WENN es decimal ist, in einen String umwandle, Mehr Hilfe brauche ich nicht.

Stattdessen wird mir hier aber versucht zu erklären warum ich garkeinen String verwenden soll und inzwischen hat sich die Diskussion so weit verselbstständigt das man meint man müssen mir in einem Python-Forum erklären wie man StarBasic programmiert. Ich will aber garnichts zu StarBasic wissen, sonst würde in in einen dazu passenden Forum fragen z.B. bei http://de.openoffice.info/index.php wo ich zufällig sogar selbst Moderator bin...


Gruß
Stephan
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Du denkst, Du müßtest in Python etwas in einen String umwandeln. Das ist aber der falsche Weg, wie wir Dir hier versuchen zu vermitteln. In Wirklichkeit ist das ein StarBasic oder OpenOffice-Problem, das Du aber an der falschen Stelle zu lösen versuchst.
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Du denkst, Du müßtest in Python etwas in einen String umwandeln. Das ist aber der falsche Weg, wie wir Dir hier versuchen zu vermitteln. In Wirklichkeit ist das ein StarBasic oder OpenOffice-Problem, das Du aber an der falschen Stelle zu lösen versuchst.
Das es der falsche Weg ist ist eine reine, unbewiesene Behauptung. Es tut mir leid das schreiben zu müssen, nur so ist die Situation.

Darüber hinaus gibt es eine ganz praktische Wahrheit:
da ich, trotz 15 Jahren Erfahrung, den angeblich existierenden, richtigeren, Weg überhaupt nicht kenne, nützt es mir überhaupt nichts wenn man mir nur sagt das es ihn gäbe, sondern man müsste ihn mir dann komplett aufzeigen - Letzteres wäre aber wohl eine völlig überzogene Forderung, denn wie könnte es angemessen sein in einem Python-Forum quasi Nachhilfe zu StarBasic zu verlangen?

Ich wiederhole mich, wen ich schreibe:
Worin liegt der Frevel einen nicht optimalen Weg gehen zu wollen, sofern dass überhaupt meine Absicht wäre (was es garnicht ist)? Woraus leitet sich meine Verpflichtung [sic] ab, die Implementierung wählen zu müssen die man mir hier nahelegen will ... ja, es scheint eine Verpflichtung zu sein, denn man fühlt sich ja quasi moralisch berechtigt mir andere Hilfe zu verweigern, obwohl diese möglich wäre.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Nachdem ich den Thread nun auch gelesen habe, sehe ich keine Form von Frevel oder "Hilfeverweigerung", sondern zwei Optionen:

Entweder liegst Du falsch in der Annahme, dass ausschließlich Strings als Input für die von Dir genutzte API geeignet sind. Die Vermutung ist nicht ganz abwegig, würde Dein Problem erheblich vereinfachen und mögliche Folgeprobleme vermeiden – und in dem Sinne sind hier auch einige Antworten ausgefallen.

Oder es sind als Eingangswerte für die API wirklich ausschließlich Strings geeignet. Das wäre zwar aus verschiedenen Gründen nicht "optimal", aber in dem Sinne hat rogerb bereits die zielführende Frage gestellt, welcher Datentyp aus der Datenbankabfrage denn geliefert wird. An der Stelle bist Du in der Python-Domäne und der Datentyp braucht nur noch korrekt umgewandelt und ggf. formatiert zu werden. Und dazu hatte __deets__ bereits Anfangs den Hinweis auf babel gegeben.

Das alles war hilfreich. Wo kommst Du nicht weiter?
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Entweder liegst Du falsch in der Annahme, dass ausschließlich Strings als Input für die von Dir genutzte API geeignet sind. Die Vermutung ist nicht ganz abwegig, würde Dein Problem erheblich vereinfachen und mögliche Folgeprobleme vermeiden – und in dem Sinne sind hier auch einige Antworten ausgefallen.
Ja, gut formuliert. Ich sehe das genauso obwohl es quasi infrage stellt das meine Behauptung (es brauche Strings) richtig sein muss, denn ich bin offen für eine Korrektur meines Wissens.
(einzig geht es hier um Etwas womit ich seit 15 Jahren arbeite und ich werde nicht einfach eine Behauptung akzeptieren, wenn dann brauchte es einen konkreten Code-Beweis - und da beisst sich die Katze insofern in den Schwanz als das ich mir bewusst bin das es, rein schon der Arbeit wegen, unangemessen ist einen solchen Beweis hier zu fordern)
Oder es sind als Eingangswerte für die API wirklich ausschließlich Strings geeignet. Das wäre zwar aus verschiedenen Gründen nicht "optimal", aber in dem Sinne hat rogerb bereits die zielführende Frage gestellt, welcher Datentyp aus der Datenbankabfrage denn geliefert wird. An der Stelle bist Du in der Python-Domäne und der Datentyp braucht nur noch korrekt umgewandelt und ggf. formatiert zu werden.
Und Letzteres war der Grund für mich diesen Thread hier zu eröffnen.
Wo kommst Du nicht weiter?
Der Thread ist, ab einem bestimmten Punkt, etwas zerfasert, aber: ich hatte momentan geschrieben:

"Danke. Das muss ich jetzt erst einmal durcharbeiten."

Und das muss ich jetzt auch erst einmal tun. Weil andere Dinge meine Aufmerksamkeit derzeitig beanspruchen, bin ich dazu noch nicht gekommen.

Möglicherweise werde ich aber auch einen neuen Thread beginnen, weil mir inzwischen bewusst wird das es die Dinge nicht unbedingt vereinfacht das ich hier nach einem einzelnen Datentyp (decimal) gefragt habe, denn eigentlich geht es ja darum das letztendlich die gesamte Rückgabe der Datenbankabfrage ggf. umformatiert werden muss. In StarBasic fiele mir diese Umformung leicht, aber dort ist sie viel zu langsam, sie muss also in Python erledigt werden.

Gruß
Stephan
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Stephan_2021 hat geschrieben: Mittwoch 22. September 2021, 08:10 (einzig geht es hier um Etwas womit ich seit 15 Jahren arbeite und ich werde nicht einfach eine Behauptung akzeptieren, wenn dann brauchte es einen konkreten Code-Beweis - und da beisst sich die Katze insofern in den Schwanz als das ich mir bewusst bin das es, rein schon der Arbeit wegen, unangemessen ist einen solchen Beweis hier zu fordern)
Und genau das ist der Punkt. Du weigerst Dich, zu zeigen, was Du denn wirklich tust. Du mußt es ja nicht gleich beweisen, sondern einfach nur das Stück Starbasic-Code um das es Dir geht, mal hier posten.
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

Und genau das ist der Punkt.
Nein, denn das Geschriebene ist ja eine Forderung an Dritte, die man erheben müsste, aber die ich praktisch nicht erhebe weil ich sie nicht fair finde, denn zum wiederhoilte Male kann ich nur sagen das ein Python-Forum für Python da ist und nict für StarBasic oder andere Sprachen...
Du weigerst Dich, zu zeigen, was Du denn wirklich tust.
Nein, ich weigere mch nicht und ich verbitte mir derartige unwahre Aussagen.
Ich hatte erklärt was ich tue nämlich mit Python ausgelesene Werte in ein Grid laden, Zitat:

"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)"


In Basic sieht das z.B. so aus:

Code: Alles auswählen

oMasterScriptProviderFactory = createUnoService("com.sun.star.script.provider.MasterScriptProviderFactory")
g_MasterScriptProvider = oMasterScriptProviderFactory.createScriptProvider("")
oScript = g_MasterScriptProvider.getScript("vnd.sun.star.script:mysqlgetdata2.py$get_data_for_grid?language=Python&location=user") '###
RS_Python = oScript.invoke(Array(gn_host,gn_port,gn_user,gn_pass,gn_DBName,gn_SQL_Daten),Array(),Array())
	  
tpx = UBOUND(RS_Python)
Dim gid(tpx)
For i = 0 To tpx
   gid(i) = i
Next i
	
dia_eingabe.getControl("Grid_eingabe").Model.GridDataModel.addRows(gid(), RS_Python())
Du mußt es ja nicht gleich beweisen
Ich muss ohnehin nichts beweisen und man kann auch von der Logik her nicht beweisen das etwas nicht geht, sondern nur Indizen dafür vorbringen, hingegen könnte derjenige der behauptet das etwas geht, es beweisen, sofern seine Behauptung wahr ist.
Stephan_2021
User
Beiträge: 52
Registriert: Sonntag 11. Juli 2021, 09:43

__blackjack__ hat geschrieben: Sonntag 19. September 2021, 19:32 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
Dieser Code lieferte bei mir einen Fehler weil pytest nicht gefunden werden kann. (Wohlgemerkt, ich arbeite mit LibreOffice und greife nur auf die Python-Umgebung zurück die LibreOffice mitbringt) plus mysqlk/Python).

Wenn ich pytest lösche funktioniert es:

Code: Alles auswählen

#!/usr/bin/env python3
from contextlib import closing
from decimal import Decimal
from functools import singledispatch

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()
            ]

def test_convert_to_string(value, expected):
    assert convert_to_string(value) == expected


Gruß
Stephan
Antworten