Currency formatting in Python
Asked Answered
J

15

210

I am looking to format a number like 188518982.18 to £188,518,982.18 using Python.

How can I do this?

Jolly answered 26/11, 2008 at 14:43 Comment(2)
You made an excellent point in a comment below, @RailsSon: you want to print £s to display a specific currency, but employ that display using a Japanese expression for financial numbers. I find it strange that your request hasn't been implemented in the language by decoupling the locale module's use of currency value and that currency's display properties.Zashin
@Zashin it is now, you can set LC_MONETARY and LC_NUMERIC to different locales.Hoshi
G
279

See the locale module.

This does currency (and date) formatting.

>>> import locale
>>> locale.setlocale( locale.LC_ALL, '' )
'English_United States.1252'
>>> locale.currency( 188518982.18 )
'$188518982.18'
>>> locale.currency( 188518982.18, grouping=True )
'$188,518,982.18'
Galven answered 26/11, 2008 at 14:50 Comment(14)
How would I format a non-native currency correctly, Say I'm showing a cost in GB pounds for a Japanese language report?Vashti
@TokenMacGuy: That's a Trick Question. Japanese report means japanese comma and decimal place rules but GB Pound currency symbol -- not trivially supported by Locale. You have to create a customized locale definition.Galven
if giver number is negative returns the value between "( )" why?Goalkeeper
@panchicore: I'm not sure I understand the question. Negative numbers are shown in ()'s for exactly one trivially obvious reason: that's the locale's of negative currency format. What's your real question?Galven
This still didn't work for me, but I changed it to locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') and it worked perfectly!Prot
@Furbeenator: What OS? What was your default locale setting?Galven
It is running on debian linux, the latest stable, lenny, I think. The locale is Pacific/Los Angeles, I think. In settings.py I have USE_I18N = False and USE_L10N = False but I couldn't find the actual locale it was using.Prot
@Goalkeeper the notation for negative numbers as denoted by parentheses is a common practice in the world of accounting. Try it in oocalc or excel, and format the numbers to the accounting type.Zashin
How do I generate '€188.518.982,18' ? (yes, this is the correct formatting in certain countries)Scauper
@Gevorg locale.currency( 188518982.18 ).replace('.', ',').replace(',', '.')Carmelitacarmelite
Regarding the parentheses around negatives for US Dollars, I added a clause in my use case to prepend negative signs. Having both indicators maybe redundant, but is more clear and distinct to my mind. When it's a display option for you, I'd recommend making them red vs black too...Theodicy
>>print(locale.getdefaultlocale()[0]) if it is not set to 'en_US' it will throw errorCriticism
For UK users, the following amendment worked for me: locale.setlocale(locale.LC_ALL, 'en-GB')Almita
it works for USD, but not for all currencies as it depends on localesEnsanguine
O
114

New in 2.7

>>> '{:20,.2f}'.format(18446744073709551616.0)
'18,446,744,073,709,551,616.00'

http://docs.python.org/dev/whatsnew/2.7.html#pep-0378

Ought answered 3/8, 2010 at 5:20 Comment(7)
That's neat but doesn't really answer the question, as the requested solution would include a currency symbol, and you are also hard-coding the number of digits after the decimal, which is locale-specific. There are many more reasons to use the accepted locale answer if you don't just want comma placement.Sacral
@Sacral There are also many reasons not to use the accepted locale answer, such as not importing an entire module.Bodrogi
@Josh, "from locale import currency".Jeanicejeanie
@mrooney: You can just do: '${:0,.2f}'.format(184467616.1), and you now have the symbolBarrington
@Barrington that would result in $ 123,456.78 sometimes though. Edit: markdown takes out the extra spaces, pretend there's more between the $ and the numbersHoagy
@Barrington Also, the 0 is implicit / unnecessary, i.e. '${:,.2f}'.format(184467616.1) has the same effect.Sopping
This answer is useful for those of us who came to this question simply looking for how to include commas, but instead asked how to format currency.Sandglass
D
58

Not quite sure why it's not mentioned more online (or on this thread), but the Babel package (and Django utilities) from the Edgewall guys is awesome for currency formatting (and lots of other i18n tasks). It's nice because it doesn't suffer from the need to do everything globally like the core Python locale module.

The example the OP gave would simply be:

>>> import babel.numbers
>>> import decimal
>>> babel.numbers.format_currency( decimal.Decimal( "188518982.18" ), "GBP" )
£188,518,982.18
Dann answered 13/1, 2012 at 13:17 Comment(4)
Very late note: Testing this, it does not appear to intelligently format currency, as it simply sticks the appropriate symbol before the amount (formatted in what appears to be the locale you have set, which is reasonable), regardless of whether that currency actually uses its symbol as a prefix.Bearded
@Bearded What do you mean? See babel.pocoo.org/en/latest/api/…Kaja
@Kaja It looks like the locale argument to format_currency can be used to address this, but either that wasn't in the doc four years ago (when I wrote that comment) or I just tested this answer's code as-is without checking the doc.Bearded
@Bearded Gotcha. I must have been not paying attention to the age of this post yesterday. The documentation/function changing seems very likely. Cheers!Kaja
I
54

This is an ancient post, but I just implemented the following solution which:

  • Doesn't require external modules
  • Doesn't require creating a new function
  • Can be done in-line
  • Handles multiple variables
  • Handles negative dollar amounts

Code:

num1 = 4153.53
num2 = -23159.398598

print 'This: ${:0,.0f} and this: ${:0,.2f}'.format(num1, num2).replace('$-','-$')

Output:

This: $4,154 and this: -$23,159.40

And for the original poster, obviously, just switch $ for £

Iodism answered 12/3, 2017 at 21:49 Comment(2)
my format needed some customization, but that's OK because I was able to do that with this solution.Drumfish
Cool idea! With Python 3.6 and f-strings, it looks even more beautiful: print(f'Value is: ${value:,.2f}'.replace('$-', '-$'))Jawbreaker
T
27

"{:0,.2f}".format(float(your_numeric_value)) in Python 3 does the job; it gives out something like one of the following lines:

10,938.29
10,899.00
10,898.99
2,328.99
Tepper answered 4/8, 2019 at 16:59 Comment(0)
W
18

My locale settings seemed incomplete, so I had too look beyond this SO answer and found:

http://docs.python.org/library/decimal.html#recipes

OS-independent

Just wanted to share here.

Worl answered 4/7, 2009 at 16:41 Comment(1)
But where do we call the def moneyfmt(value, places=2, curr='', sep=',', dp='.', pos='', neg='-', trailneg='')?Repertory
V
12

If you are using OSX and have yet to set your locale module setting this first answer will not work you will receive the following error:

Traceback (most recent call last):File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/locale.py", line 221, in currency
raise ValueError("Currency formatting is not possible using "ValueError: Currency formatting is not possible using the 'C' locale.

To remedy this you will have to do use the following:

locale.setlocale(locale.LC_ALL, 'en_US')
Virgule answered 5/10, 2010 at 17:8 Comment(1)
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') does for meDamper
P
10

If I were you, I would use BABEL: http://babel.pocoo.org/en/latest/index.html

from babel.numbers import format_decimal


format_decimal(188518982.18, locale='en_US')
Petey answered 22/2, 2018 at 22:14 Comment(1)
The python locale module didn't work for me (whatever locale I set it, it complained) but requiring babel and using this function is nice. It's worth having a look in the API docs as there are more parameters and more useful functions (like for currencies: format_currency).Alexine
K
10

There are already a dozen solutions here, but I believe the one below is the best, because:

  • it is simple
  • obeys the OS locale
  • no external lib is needed
  • you can make it concise

My solution is to use locale.currency() method:

import locale
# this sets locale to the current Operating System value
locale.setlocale(locale.LC_ALL, '') 
print(locale.currency(1346896.67444, grouping=True, symbol=True)

will output in my Windows 10 configured to Brazilian Portuguese:

R$ 1.346.896,67

It is somewhat verbose, so if you will use it a lot, maybe it is better to predefine some parameters and have a shorter name and use it inside a f-string:

fmt = lambda x: locale.currency(x, grouping=True, symbol=True)
print(f"Value: {fmt(1346896.67444)}"

You can pass a locale value for the setlocale method, but its value is OS dependent, so beware. If you are in a *nix server, you also need to check if your desired locale is correctly installed in the OS.

You also can turn off the symbol passing symbol=False.

Kilo answered 12/5, 2021 at 19:56 Comment(0)
C
3

Oh, that's an interesting beast.

I've spent considerable time of getting that right, there are three main issues that differs from locale to locale: - currency symbol and direction - thousand separator - decimal point

I've written my own rather extensive implementation of this which is part of the kiwi python framework, check out the LGPL:ed source here:

http://svn.async.com.br/cgi-bin/viewvc.cgi/kiwi/trunk/kiwi/currency.py?view=markup

The code is slightly Linux/Glibc specific, but shouldn't be too difficult to adopt to windows or other unixes.

Once you have that installed you can do the following:

>>> from kiwi.datatypes import currency
>>> v = currency('10.5').format()

Which will then give you:

'$10.50'

or

'10,50 kr'

Depending on the currently selected locale.

The main point this post has over the other is that it will work with older versions of python. locale.currency was introduced in python 2.5.

Cyrilcyrill answered 26/11, 2008 at 15:6 Comment(2)
Does it have advantages over locale.currency() ?Cornejo
@AliAfshar: One advantage would be 10,50 kr instead of kr 10,50.Fencesitter
P
3

#printing the variable 'Total:' in a format that looks like this '9,348.237'

print ('Total:',   '{:7,.3f}'.format(zum1))

where the '{:7,.3f}' es the number of spaces for formatting the number in this case is a million with 3 decimal points. Then you add the '.format(zum1). The zum1 is tha variable that has the big number for the sum of all number in my particular program. Variable can be anything that you decide to use.

Pecan answered 21/11, 2016 at 17:16 Comment(0)
N
2

Inspired by the code above :D

def money_format(value):
    value = str(value).split('.')
    money = ''
    count = 1

    for digit in value[0][::-1]:
        if count != 3:
            money += digit
            count += 1
        else:
            money += f'{digit},'
            count = 1

    if len(value) == 1:
        money = ('$' + money[::-1]).replace('$-','-$')
    else:
        money = ('$' + money[::-1] + '.' + value[1]).replace('$-','-$')

    return money
Novikoff answered 25/6, 2020 at 14:27 Comment(0)
K
0

A lambda for calculating it inside a function, with help from @Nate's answer

converter = lambda amount, currency: "%s%s%s" %(
    "-" if amount < 0 else "", 
    currency, 
    ('{:%d,.2f}'%(len(str(amount))+3)).format(abs(amount)).lstrip())

and then,

>>> converter(123132132.13, "$")
'$123,132,132.13'

>>> converter(-123132132.13, "$")
'-$123,132,132.13'
Kerekes answered 6/11, 2014 at 4:18 Comment(2)
Most countries use the currency symbol after the amount, not the other way around.Piperidine
@jonas Maybe that's what most countries do, but OP had it before the amount, hence I've got it before the amount in my answer too :)Kerekes
C
0

Simple python code!

def format_us_currency(value):
    value=str(value)
    if value.count(',')==0:
        b,n,v='',1,value
        value=value[:value.rfind('.')]
        for i in value[::-1]:
            b=','+i+b if n==3 else i+b
            n=1 if n==3 else n+1
        b=b[1:] if b[0]==',' else b
        value=b+v[v.rfind('.'):]
    return '$'+(value.rstrip('0').rstrip('.') if '.' in value else value)
Criticism answered 8/4, 2019 at 12:41 Comment(2)
Your code returns strings like "$2,129.1468284147656", "$10,948.3742933", "$1,0908". Garbles the string.Tepper
Yes I didn't notice. You have given the ans too.Criticism
J
0

With only Python Standard Library imports, this is a compact way of defining a custom format:

>>> from functools import partial
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')  # or whatever locale you want
>>> _c = partial(locale.currency, grouping=True)
>>> my_amount = 188518982.18
>>> print(f'{_c(my_amount)}')
$188,518,982.18
Jook answered 4/3, 2024 at 17:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.