Reputation: 18017
I learn from Currency formatting in Python, use the locale module to format numbers as currency. For instance,
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import locale
value = 123456789
l = locale.setlocale(locale.LC_ALL, '') # LC_CTYPE=en_US.UTF-8;LC_NUMERIC=fr_FR.UTF-8;LC_TIME=fr_FR.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=fr_FR.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=fr_FR.UTF-8;LC_NAME=fr_FR.UTF-8;LC_ADDRESS=fr_FR.UTF-8;LC_TELEPHONE=fr_FR.UTF-8;LC_MEASUREMENT=fr_FR.UTF-8;LC_IDENTIFICATION=fr_FR.UTF-8
s = locale.currency(value, grouping=True) # 123 456 789,00 €
locale.setlocale(locale.LC_ALL, 'en_US.utf-8')
s = locale.currency(value, grouping=True) # $123,456,789.00
locale.setlocale(locale.LC_ALL, 'en_US') # WHY? locale.Error: unsupported locale setting
s = locale.currency(value, grouping=True)
I'd like to format numbers to other currency, say de_DE
. I encounter the issue locale.Error: unsupported locale setting
since the locale de_DE
is not in the list of locale -a
.
locale.setlocale(locale.LC_ALL, 'de_DE') # locale.Error: unsupported locale setting
s = locale.currency(value, grouping=True)
One solution is to add this locale to my machine. Is there a better way?
Upvotes: 13
Views: 34328
Reputation: 3729
I know of two solutions to this:
Babel
Babel is the best solution because you can choose any currency, regardless of the locale.
The down side is that it's poorly documented. To know all the options, you'll have to read the Babel source code for the function you want to use
Install Babel:
$ pip install Babel
How to use:
import babel.numbers
amount = 123456789.123
print(babel.numbers.format_currency(amount, 'EUR', locale='fr_CA'))
# 123 456 789,12 €
print(babel.numbers.format_currency(amount, 'EUR', locale='en_CA'))
# €123,456,789.12
print(babel.numbers.format_currency(amount, '', locale='en_CA'))
# 123,456,789.12
localize.currency()
One limitation of locale.currency()
is that it presumes the currency that matches the locale. For example en_US => $/USD
and fr_FR => €/EUR
So you may want to use the String.replace()
method to replace the currency symbol after if the displayed currency doesn't match the locale.
Based on the locale setting, for example en_US
or en_GB
, fr_FR
or fr_CA
, it will know:
100.00
vs 100,00
)1,000
vs 1.000
)$100
vs €100
or USD 100
vs EUR 100
)$100
vs 100 $
)import locale
locale.setlocale(locale.LC_ALL, 'fr_FR')
amount = 123456789.123
grouping = True # thousands separator
# '123.456.789,12 Eu'
locale.currency(amount, symbol=True, grouping=True, international=False)
# '123.456.789,12 EUR'
locale.currency(amount, symbol=True, grouping=True, international=False)
# '123.456,789'
locale.currency(amount, symbol=False, grouping=True)
# '123456,789'
locale.currency(amount, symbol=False, grouping=True)
The optional arguments are as follows
# which currency symbol to use, and where to place it
symbol=True and international=True # => 'USD 100.00'
symbol=True and international=False # => '$100.00'
symbol=False # => '100.00'
# thousands separator
grouping = True # => '1000.00'
grouping = False # => '1,000.00'
Upvotes: 1
Reputation: 41
For reference (for those that are looking to format numbers similar to how you would format currency), you can use locale.format_string to format numbers
value = 123456789
import locale
locale.setlocale(locale.LC_ALL, 'de_DE')
print(locale.format_string('%.2f', value, True))
Would return
123.456.789,00
Upvotes: 4
Reputation: 180441
In [22]: from babel.numbers import format_decimal
In [23]: format_decimal(12345, locale='de_DE')
Out[23]: u'12.345'
In [24]: format_decimal(1.2345, locale='sv_SE')
Out[24]: u'1,234'
Or in your case format_currency:
In [7]: from babel.numbers import format_currency
In [8]: print format_currency(1099.98, 'USD', locale='en_US')
$1,099.98
In [9]: print format_currency(1099.98, 'USD', locale='es_CO')
1.099,98 US$
In [10]: print format_currency(1099.98, 'EUR', locale='de_DE')
1.099,98 €
Upvotes: 11