Formatowanie walut w Pythonie

156

Chcę sformatować liczbę taką jak 188518982,18 do 188 518 982,18 GBP za pomocą Pythona.

W jaki sposób mogę to zrobić?

RailsSon
źródło
W poniższym komentarzu @RailsSon wskazałeś na doskonały punkt: chcesz wydrukować funty, aby wyświetlić określoną walutę, ale zastosuj ten sposób wyświetlania, używając japońskiego wyrażenia dla liczb finansowych. Wydaje mi się dziwne, że twoje żądanie nie zostało zaimplementowane w języku poprzez oddzielenie localeużycia wartości waluty przez moduł i właściwości wyświetlania tej waluty.
Droogans

Odpowiedzi:

212

Zobacz moduł locale .

Dotyczy to formatowania waluty (i daty).

>>> 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'
S.Lott
źródło
15
Jak poprawnie sformatować obcą walutę, powiedzmy, że pokazuję koszt w funtach brytyjskich dla raportu w języku japońskim?
SingleNegationElimination,
2
@TokenMacGuy: To podstępne pytanie. Raport japoński oznacza japońskie zasady dotyczące przecinków i miejsc dziesiętnych, ale symbol waluty funta GB - nie jest trywialnie obsługiwany przez Locale. Musisz utworzyć niestandardową definicję ustawień regionalnych.
S.Lott,
jeśli liczba dawcy jest ujemna, zwraca wartość między „()”, dlaczego?
panchicore
6
To nadal nie działało dla mnie, ale zmieniłem to locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')i działało idealnie!
Furbeenator
2
@panchicore notacja liczb ujemnych zapisywana w nawiasach jest powszechną praktyką w świecie rachunkowości. Wypróbuj w oocalc lub excel i sformatuj liczby zgodnie z typem rozliczania.
Droogans
94

Nowość w wersji 2.7.0

>>> '{: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
źródło
6
To fajne, ale tak naprawdę nie odpowiada na pytanie, ponieważ żądane rozwiązanie zawierałoby symbol waluty, a także wpisujesz na stałe liczbę cyfr po przecinku, co jest specyficzne dla lokalizacji. Istnieje wiele innych powodów, dla których warto użyć akceptowanej odpowiedzi dotyczącej języka, jeśli nie chcesz umieszczać tylko przecinków.
mrooney
6
@mrooney Istnieje również wiele powodów, dla których nie należy używać akceptowanej odpowiedzi dotyczącej ustawień regionalnych, na przykład nie importowanie całego modułu.
Josh
1
@Josh, „z lokalnej waluty importu”.
Andrew H
5
@mrooney: Możesz po prostu zrobić: format „$ {: 0, .2f}” (184467616.1) i masz teraz symbol
triunenature
@triunenature, co $ 123,456.78czasami skutkuje . Edycja:
Markdown usuwa
48

Nie do końca jestem pewien, dlaczego nie wspomniano o tym więcej w Internecie (lub w tym wątku), ale pakiet Babel (i narzędzia Django) od facetów z Edgewall jest świetny do formatowania walut (i wielu innych zadań i18n). To fajne, ponieważ nie cierpi z powodu konieczności robienia wszystkiego globalnie, jak rdzeń modułu lokalnego dla Pythona.

Przykład podany przez PO wyglądałby po prostu:

>>> import babel.numbers
>>> import decimal
>>> babel.numbers.format_currency( decimal.Decimal( "188518982.18" ), "GBP" )
£188,518,982.18
glenc
źródło
2
Bardzo późna uwaga: testując to, nie wydaje się, aby inteligentnie formatował walutę, ponieważ po prostu umieszcza odpowiedni symbol przed kwotą (sformatowaną w ustawionym przez Ciebie ustawieniu regionalnym, co jest rozsądne), niezależnie od tego, czy ta waluta faktycznie używa swojego symbolu jako przedrostka.
kungphu
@kungphu Co masz na myśli? Zobacz babel.pocoo.org/en/latest/api/…
Julian
1
@Julian Wygląda na to, że locale argument do format_currencymoże zostać użyty do rozwiązania tego problemu, ale albo tego nie było w dokumencie cztery lata temu (kiedy pisałem ten komentarz), albo właśnie przetestowałem kod tej odpowiedzi bez sprawdzania dokumentu.
kungphu
1
@kungphu Gotcha. Wczoraj chyba nie zwracałem uwagi na wiek tego wpisu. Zmiana dokumentacji / funkcji wydaje się bardzo prawdopodobna. Twoje zdrowie!
Julian
32

To jest starożytny post, ale właśnie wdrożyłem następujące rozwiązanie, które:

  • Nie wymaga zewnętrznych modułów
  • Nie wymaga tworzenia nowej funkcji
  • Można to zrobić w linii
  • Obsługuje wiele zmiennych
  • Obsługuje ujemne kwoty w dolarach

Kod:

num1 = 4153.53
num2 = -23159.398598

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

Wynik:

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

A jeśli chodzi o oryginalny plakat, po prostu przełącz się $na£

elPastor
źródło
mój format wymagał dostosowania, ale to jest w porządku, ponieważ mogłem to zrobić za pomocą tego rozwiązania.
DonkeyKong
9
Fajny pomysł! Z Pythonem 3.6 i f-stringami wygląda jeszcze piękniej:print(f'Value is: ${value:,.2f}'.replace('$-', '-$'))
Timo Saloranta
16

Moje ustawienia regionalne wydawały się niekompletne, więc również spojrzałem poza tę TAK odpowiedź i znalazłem:

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

Niezależny od systemu operacyjnego

Chciałem się tu tylko podzielić.

user37986
źródło
Ale gdzie nazywamy to def moneyfmt(value, places=2, curr='', sep=',', dp='.', pos='', neg='-', trailneg='')?
Roel
9

Jeśli używasz OSX i nie ustawiłeś jeszcze swojego modułu ustawień regionalnych, to pierwsza odpowiedź nie zadziała, pojawi się następujący błąd:

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.

Aby temu zaradzić, będziesz musiał wykonać następujące czynności:

locale.setlocale(locale.LC_ALL, 'en_US')
Simoes
źródło
2
locale.setlocale (locale.LC_ALL, 'en_US.UTF-8') robi dla mnie
alexblum
9

"{:0,.2f}".format(float(your_numeric_value))w Pythonie 3 spełnia swoje zadanie; wyświetla coś podobnego do jednej z następujących linii:

10,938.29
10,899.00
10,898.99
2,328.99
Eugene Gr. Philippov
źródło
6

Na twoim miejscu użyłbym BABEL: http://babel.pocoo.org/en/latest/index.html

from babel.numbers import format_decimal


format_decimal(188518982.18, locale='en_US')
Carlos
źródło
1
Moduł locale Pythona nie działał dla mnie (niezależnie od ustawień lokalnych, narzekał), ale wymaganie Babel i używanie tej funkcji jest przyjemne. Warto zajrzeć do dokumentacji API, ponieważ jest więcej parametrów i bardziej przydatnych funkcji (jak dla walut:) format_currency.
Daniel W.
3

Och, to interesująca bestia.

Spędziłem dużo czasu, aby to naprawić, istnieją trzy główne kwestie, które różnią się w zależności od lokalizacji: - symbol waluty i kierunek - separator tysięcy - przecinek dziesiętny

Napisałem własną, dość obszerną implementację tego, która jest częścią frameworka kiwi Python, sprawdź źródło LGPL: ed tutaj:

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

Kod jest nieco specyficzny dla Linuksa / Glibc, ale nie powinien być zbyt trudny do zaadaptowania do Windows lub innych uniksów.

Po zainstalowaniu możesz wykonać następujące czynności:

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

Który następnie da ci:

'$10.50'

lub

'10,50 kr'

W zależności od aktualnie wybranej lokalizacji.

Głównym punktem, który ten post ma nad innymi, jest to, że będzie działać ze starszymi wersjami Pythona. locale.currency zostało wprowadzone w Pythonie 2.5.

Johan Dahlin
źródło
Czy ma przewagę nad locale.currency ()?
Ali Afshar
@AliAfshar: 10,50 krZamiast tego byłaby jedna korzyść kr 10,50.
user2394284
2

#printing zmiennej „Total:” w formacie, który wygląda następująco: „9,348,237”

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

gdzie „{: 7, .3f}” to liczba spacji do sformatowania liczby w tym przypadku to milion z 3 miejscami po przecinku. Następnie dodajesz '.format (zum1). Zum1 to zmienna, która ma dużą liczbę będącą sumą wszystkich liczb w moim konkretnym programie. Zmienna może być wszystkim, czego zdecydujesz się użyć.

Marie
źródło
1

Zainspirowany powyższym kodem: 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
Elmer Gonzalez
źródło
0

Przyszedłem spojrzeć na to samo i stwierdziłem, że pieniądze z Pythona jeszcze go nie używają, ale może połączenie tych dwóch byłoby dobre

James Brooks
źródło
0

Lambda do obliczania jej wewnątrz funkcji, z pomocą odpowiedzi @ Nate'a

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

i wtedy,

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

>>> converter(-123132132.13, "$")
'-$123,132,132.13'
mu 無
źródło
Większość krajów używa symbolu waluty po kwocie, a nie odwrotnie.
Jonas Byström
@jonas Może tak robi większość krajów, ale OP miał to przed kwotą, stąd też mam to przed kwotą w mojej odpowiedzi :)
mu 無
0

Prosty kod w Pythonie!

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
źródło
1
Przywracany kod ciągi podoba "$2,129.1468284147656", "$10,948.3742933", "$1,0908". Niszczy sznurek.
Eugene Gr. Philippov
Tak, nie zauważyłem. Ty też dałeś odpowiedzi.
Vanjith