204

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

How can I do this?

vaultah
  • 44,105
  • 12
  • 114
  • 143
RailsSon
  • 19,897
  • 31
  • 82
  • 105
  • 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. – yurisich Jan 13 '12 at 13:56
  • 1
    @yurisich it is now, you can set LC_MONETARY and LC_NUMERIC to different locales. – Iuri Guilherme Jul 16 '22 at 07:38

14 Answers14

274

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'
Taylor D. Edmiston
  • 12,088
  • 6
  • 56
  • 76
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 16
    How would I format a non-native currency correctly, Say I'm showing a cost in GB pounds for a Japanese language report? – SingleNegationElimination Jul 04 '09 at 16:44
  • 3
    @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. – S.Lott Jul 04 '09 at 17:10
  • if giver number is negative returns the value between "( )" why? – panchicore Oct 24 '09 at 20:07
  • @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? – S.Lott Oct 24 '09 at 21:29
  • 10
    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! – Furbeenator Dec 12 '11 at 20:53
  • @Furbeenator: What OS? What was your default locale setting? – S.Lott Dec 12 '11 at 23:06
  • 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. – Furbeenator Dec 13 '11 at 01:04
  • 3
    @panchicore 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. – yurisich Jan 13 '12 at 14:00
  • How do I generate '€188.518.982,18' ? (yes, this is the correct formatting in certain countries) – Marsellus Wallace Feb 12 '18 at 15:28
  • @Gevorg `locale.currency( 188518982.18 ).replace('.', ',').replace(',', '.')` – Artemis May 01 '18 at 20:10
  • 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... – BuvinJ May 08 '18 at 14:21
  • `>>print(locale.getdefaultlocale()[0])` if it is not set to 'en_US' it will throw error – Vanjith Apr 08 '19 at 13:21
  • For UK users, the following amendment worked for me: `locale.setlocale(locale.LC_ALL, 'en-GB')` – Jayce May 03 '19 at 22:30
  • it works for USD, but not for all currencies as it depends on locales – dnuske May 19 '20 at 18:10
112

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

nate c
  • 8,802
  • 2
  • 27
  • 28
  • 11
    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. – mrooney Jun 24 '13 at 19:44
  • 8
    @mrooney There are also many reasons not to use the accepted locale answer, such as not importing an entire module. – Josh Dec 31 '14 at 04:19
  • 1
    @Josh, "from locale import currency". – Andrew H Jul 27 '15 at 22:27
  • 6
    @mrooney: You can just do: '${:0,.2f}'.format(184467616.1), and you now have the symbol – triunenature Sep 30 '15 at 23:55
  • 2
    @triunenature that would result in `$ 123,456.78` sometimes though. Edit: markdown takes out the extra spaces, pretend there's more between the $ and the numbers – Foxocube Jul 25 '16 at 10:40
  • 1
    @triunenature Also, the 0 is implicit / unnecessary, i.e. `'${:,.2f}'.format(184467616.1)` has the same effect. – Taylor D. Edmiston Oct 21 '16 at 16:17
  • 1
    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. – young_souvlaki Sep 16 '20 at 04:20
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
Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
glenc
  • 3,132
  • 2
  • 26
  • 42
  • 3
    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. – kungphu Jan 09 '15 at 03:57
  • @kungphu What do you mean? See http://babel.pocoo.org/en/latest/api/numbers.html#babel.numbers.format_currency – Julian Jan 31 '19 at 14:42
  • 1
    @Julian 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. – kungphu Feb 01 '19 at 06:02
  • 1
    @kungphu Gotcha. I must have been not paying attention to the age of this post yesterday. The documentation/function changing seems very likely. Cheers! – Julian Feb 01 '19 at 16:00
52

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 £

elPastor
  • 8,435
  • 11
  • 53
  • 81
25

"{: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
Eugene Gr. Philippov
  • 1,908
  • 2
  • 23
  • 18
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.

user37986
  • 1,107
  • 2
  • 11
  • 12
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')
simoes
  • 4,897
  • 4
  • 23
  • 28
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')
Carlos
  • 727
  • 7
  • 11
  • 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`). – Daniel W. Jun 17 '19 at 21:15
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.

neves
  • 33,186
  • 27
  • 159
  • 192
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.

Johan Dahlin
  • 25,300
  • 6
  • 40
  • 55
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.

Marie
  • 31
  • 1
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
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'
Community
  • 1
  • 1
Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
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)
Vanjith
  • 520
  • 4
  • 23