Is there a simple and preferred way of German number string formatting in Python?
Asked Answered
T

4

7

I am searching for the proper way of German number formatting (e.g. 1.000,1234) in Python under Windows OS.

I tried locale.setlocale but did not succeed.

Instead, I have written a function to come up with the desired output.

Is there a better way?

def ger_num(number, precision=3):
    """
    returns german formatted number as string or an empty string
    """
    if number is not None:
        try:
            my_number = "{:,f}".format(number)
        except ValueError:
            return ""

        decimals, fraction = my_number.split(".")[0], my_number.split(".")[1]
        decimals = decimals.replace(",", ".")

        if precision:
            return decimals + "," + fraction[:precision]
        else:
            return decimals

    else:
        return ""
Tehuantepec answered 10/4, 2019 at 15:40 Comment(2)
please provide a clear description of your inputs and outputs.Merrymaker
What exactly have you tried with locale? Perhaps your platform doesn't support it? See the many answers here: #14287551Disinfect
A
5

You can use locale.setlocale to set the locale to de and then use locale.format to format your number:

import locale
locale.setlocale(locale.LC_ALL, 'de')
print(locale.format('%.4f', 1000.1234, 1))

This outputs:

1.000,1234
Afrikaans answered 10/4, 2019 at 16:0 Comment(1)
On Debian you might want to check your specific locale identifiers by running locale -a and if it's missing check out man locale-gen. I'm using de_DE.utf8. Also, locale.format is deprecated in Python 3.7. Use locale.format_string() instead.Firedamp
M
4

If for some reason locale does not work for you (or is not desired), then the easiest other option would probably be to use string replacement, like suggested in this already mentioned answer (which draws its answer from the PEP-378).

You can always encapsulate that in a function, maybe like this:

def format_number(number, precision=3):
    # build format string
    format_str = '{{:,.{}f}}'.format(precision)

    # make number string
    number_str = format_str.format(number)

    # replace chars
    return number_str.replace(',', 'X').replace('.', ',').replace('X', '.')

This works well for int, float and Decimal:

>>> format_number(1)
'1,000'
>>> format_number(1, 2)
'1,00'
>>> format_number(1, 7)
'1,0000000'
>>> format_number(1234567, 7)
'1.234.567,0000000'

>>> format_number(1234567.9988, 7)
'1.234.567,9988000'
>>> format_number(1234567.9988, 2)
'1.234.568,00'

>>> from decimal import Decimal
>>> format_number(Decimal('1234567.9988'), 2)
'1.234.568,00'
>>> format_number(Decimal('1234567.9988'), 5)
'1.234.567,99880'
>>> format_number(Decimal('1234567.9988'), 0)
'1.234.568'
>>> format_number(Decimal('123456'), 5)
'123.456,00000'
Maupin answered 10/4, 2019 at 16:17 Comment(1)
I was able to edit this func into something that allowed me to display euro symbol in front of euro formatted currency - much neater than worrying about localeGrader
T
0

Thanks for the help. If anyone finds this useful I do provide the code for my final solution here.

ger_num.py:

def ger_num(number, digits=2):
    '''
    retruns <number> as german formattet string (thousands-.),
    rounds to n <digits>.

    <number> == None OR (!= INT AND != FLOAT) returns '' (empty STR)
    '''
    import locale
    locale.setlocale(locale.LC_ALL, 'de')
    if number is None:
        return ''
    if not isinstance(number, int) and not isinstance(number, float):
        return ''
    else:
        format = '%.'+str(digits)+'f'
        return locale.format_string(format, number, 1)


if __name__ == "__main__":
    pass
Tehuantepec answered 21/5, 2019 at 8:26 Comment(0)
C
0

If locale has an for you issue again, I would propose simple string replacement. The proposed format_number function above is great, but it does not always preserve the input. For instance, format_number(Decimal('1234567.9988'), 0) does transform English to German format, but it removes the numbers after the decimal point. A simple safe way to just tranform any English string number to a German string number is this:

de_number = number.replace(".", "$DECIMAL$")
de_number = de_number.replace(",", ".")
de_number = de_number.replace("$DECIMAL$", ",")

From the post I gathered that the input number is always positive, but in case it can be negative, you could use number[1:]instead of number. If the majority of the input numbers are negative, it might worth using locale, which seems to deal with them by default.

To format an input German string number into an English string number without altering the input again, use:

en_number = number.replace(",", "$DECIMAL$")
en_number = en_number.replace(".", ",")
en_number = en_number.replace("$DECIMAL$", ".")

If en_number does not have thousand separators but only decimal points, it can now be properly used in Python like in float(en_number). For instance, float("5000.0") works, but the German equivalent float("5000,0") would give a ValueError.

Clein answered 21/8, 2023 at 8:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.