Währungsformatierung in Python


156

Ich möchte eine Zahl wie 188518982.18 mit Python auf £ 188.518.982,18 formatieren.

Wie kann ich das machen?


Sie haben in einem Kommentar unten, @RailsSon, einen hervorragenden Punkt hervorgehoben: Sie möchten £ s drucken, um eine bestimmte Währung anzuzeigen, verwenden diese Anzeige jedoch mit einem japanischen Ausdruck für Finanzzahlen. Ich finde es seltsam, dass Ihre Anfrage nicht in der Sprache implementiert wurde, indem die localeVerwendung des Währungswerts durch das Modul und die Anzeigeeigenschaften dieser Währung entkoppelt wurden .
Droogans

Antworten:


212

Siehe das Gebietsschemamodul .

Dies führt die Formatierung von Währung (und Datum) durch.

>>> 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'

15
Wie würde ich eine nicht einheimische Währung korrekt formatieren? Angenommen, ich zeige Kosten in GB-Pfund für einen Bericht in japanischer Sprache an?
SingleNegationElimination

2
@TokenMacGuy: Das ist eine Trickfrage. Japanischer Bericht bedeutet japanische Komma- und Dezimalstellenregeln, aber GB-Pfund-Währungssymbol - von Locale nicht trivial unterstützt. Sie müssen eine benutzerdefinierte Gebietsschemadefinition erstellen.
S.Lott

Wenn die Gebernummer negativ ist, wird der Wert zwischen "()" zurückgegeben. Warum?
Panchicore

6
Das hat bei mir immer noch nicht funktioniert, aber ich habe es geändert locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')und es hat perfekt funktioniert!
Furbeenator

2
@panchicore Die in Klammern angegebene Notation für negative Zahlen ist in der Welt der Buchhaltung eine gängige Praxis. Probieren Sie es in oocalc oder excel aus und formatieren Sie die Zahlen auf den Buchhaltungstyp.
Droogans

94

Neu 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


6
Das ist ordentlich, beantwortet aber die Frage nicht wirklich, da die angeforderte Lösung ein Währungssymbol enthalten würde und Sie auch die Anzahl der Stellen nach der Dezimalstelle, die länderspezifisch ist, fest codieren. Es gibt viele weitere Gründe, die akzeptierte Antwort auf das Gebietsschema zu verwenden, wenn Sie nicht nur eine Komma-Platzierung wünschen.
Mrooney

6
@mrooney Es gibt auch viele Gründe, die akzeptierte Antwort auf das Gebietsschema nicht zu verwenden, z. B. nicht das Importieren eines gesamten Moduls.
Josh

1
@Josh, "aus der Gebietsschema-Importwährung".
Andrew H

5
@mrooney: Sie können einfach tun: '$ {: 0, .2f}'. Format (184467616.1), und Sie haben jetzt das Symbol
Triunenature

@ Triunenature, die $ 123,456.78manchmal aber führen würde. Bearbeiten: Markdown entfernt die zusätzlichen Leerzeichen, tun Sie so, als ob es mehr zwischen dem $ und den Zahlen gibt
CyberJacob

48

Ich bin mir nicht ganz sicher, warum es nicht mehr online (oder in diesem Thread) erwähnt wird, aber das Babel- Paket (und die Django-Dienstprogramme) der Edgewall-Leute eignet sich hervorragend für die Währungsformatierung (und viele andere i18n-Aufgaben). Es ist schön, weil es nicht unter der Notwendigkeit leidet, alles global zu erledigen, wie das Kernmodul des Python-Gebietsschemas.

Das Beispiel, das das OP gegeben hat, wäre einfach:

>>> import babel.numbers
>>> import decimal
>>> babel.numbers.format_currency( decimal.Decimal( "188518982.18" ), "GBP" )
£188,518,982.18

2
Sehr später Hinweis: Wenn Sie dies testen, scheint die Währung nicht intelligent zu formatieren, da einfach das entsprechende Symbol vor dem Betrag (formatiert in dem von Ihnen festgelegten Gebietsschema, das angemessen ist) angebracht wird, unabhängig davon, ob diese Währung tatsächlich vorhanden ist verwendet sein Symbol als Präfix.
Kungphu

@kungphu Was meinst du? Siehe babel.pocoo.org/en/latest/api/…
Julian

1
@Julian Es sieht so aus, als ob das localeArgument format_currencyverwendet werden kann, um dies zu beheben , aber entweder war das vor vier Jahren nicht im Dokument (als ich diesen Kommentar schrieb) oder ich habe den Code dieser Antwort so wie er ist getestet, ohne das Dokument zu überprüfen.
Kungphu

1
@kungphu Gotcha. Ich muss gestern nicht auf das Alter dieses Beitrags geachtet haben. Die Änderung der Dokumentation / Funktion scheint sehr wahrscheinlich. Prost!
Julian

32

Dies ist ein alter Beitrag, aber ich habe gerade die folgende Lösung implementiert:

  • Benötigt keine externen Module
  • Erfordert keine neue Funktion
  • Kann inline erfolgen
  • Behandelt mehrere Variablen
  • Behandelt negative Dollarbeträge

Code:

num1 = 4153.53
num2 = -23159.398598

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

Ausgabe:

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

Und für das Originalplakat wechseln Sie natürlich einfach $für£


Mein Format musste angepasst werden, aber das ist in Ordnung, da ich dies mit dieser Lösung tun konnte.
DonkeyKong

9
Tolle Idee! Mit Python 3.6 und F-Strings sieht es noch schöner aus:print(f'Value is: ${value:,.2f}'.replace('$-', '-$'))
Timo Saloranta

16

Meine Gebietsschemaeinstellungen schienen unvollständig zu sein, daher musste ich auch über diese SO-Antwort hinausschauen und feststellen:

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

Betriebssystemunabhängig

Ich wollte nur hier teilen.


Aber wie nennen wir das def moneyfmt(value, places=2, curr='', sep=',', dp='.', pos='', neg='-', trailneg='')?
Roel

9

Wenn Sie OSX verwenden und die Einstellung Ihres Gebietsschemamoduls noch nicht festgelegt haben, funktioniert diese erste Antwort nicht. Sie erhalten die folgende Fehlermeldung:

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.

Um dies zu beheben, müssen Sie Folgendes verwenden:

locale.setlocale(locale.LC_ALL, 'en_US')

2
locale.setlocale (locale.LC_ALL, 'en_US.UTF-8') erledigt für mich
alexblum

9

"{:0,.2f}".format(float(your_numeric_value))in Python 3 erledigt den Job; es gibt so etwas wie eine der folgenden Zeilen aus:

10,938.29
10,899.00
10,898.99
2,328.99

6

Wenn ich Sie wäre, würde ich BABEL verwenden: http://babel.pocoo.org/en/latest/index.html

from babel.numbers import format_decimal


format_decimal(188518982.18, locale='en_US')

1
Das Python-Gebietsschema-Modul hat bei mir nicht funktioniert (egal welches Gebietsschema ich festgelegt habe, es hat sich beschwert), aber es ist nett, Babel zu benötigen und diese Funktion zu verwenden. Es lohnt sich, einen Blick in die API-Dokumente zu werfen, da es mehr Parameter und nützlichere Funktionen gibt (wie für Währungen :) format_currency.
Daniel W.

3

Oh, das ist ein interessantes Tier.

Ich habe viel Zeit damit verbracht, das richtig zu machen. Es gibt drei Hauptprobleme, die sich von Gebietsschema zu Gebietsschema unterscheiden: - Währungssymbol und Richtung - Tausendertrennzeichen - Dezimalpunkt

Ich habe meine eigene ziemlich umfangreiche Implementierung davon geschrieben, die Teil des Kiwi-Python-Frameworks ist. Schauen Sie sich die LGPL: ed-Quelle hier an:

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

Der Code ist leicht Linux / Glibc-spezifisch, sollte aber nicht zu schwierig für Windows oder andere Unixe sein.

Sobald Sie das installiert haben, können Sie Folgendes tun:

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

Welches wird Ihnen dann geben:

'$10.50'

oder

'10,50 kr'

Abhängig vom aktuell ausgewählten Gebietsschema.

Der Hauptpunkt, den dieser Beitrag gegenüber dem anderen hat, ist, dass er mit älteren Python-Versionen funktioniert. locale.currency wurde in Python 2.5 eingeführt.


Hat es Vorteile gegenüber locale.currency ()?
Ali Afshar

@AliAfshar: Ein Vorteil wäre 10,50 krstatt kr 10,50.
user2394284

2

# Drucken der Variablen 'Total:' in einem Format, das wie folgt aussieht: '9,348.237'

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

Dabei ist '{: 7, .3f}' die Anzahl der Leerzeichen zum Formatieren der Zahl in diesem Fall eine Million mit 3 Dezimalstellen. Dann fügen Sie das '.format (zum1) hinzu. Das zum1 ist die Variable, die die große Zahl für die Summe aller Zahlen in meinem speziellen Programm hat. Variable kann alles sein, was Sie verwenden möchten.


1

Inspiriert vom obigen Code: 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

Ich bin gekommen, um mir das Gleiche anzusehen und habe festgestellt, dass Python-Geld es noch nicht wirklich verwendet hat, aber vielleicht wäre eine Mischung aus beiden gut


0

Ein Lambda zur Berechnung innerhalb einer Funktion mit Hilfe von @ Nates Antwort

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

und dann,

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

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

Die meisten Länder verwenden das Währungssymbol nach dem Betrag, nicht umgekehrt.
Jonas Byström

@ Jonas Vielleicht ist es das, was die meisten Länder tun, aber OP hatte es vor dem Betrag, daher habe ich es auch vor dem Betrag in meiner Antwort :)
mu 無

0

Einfacher 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)

1
Ihr Code kehrt Strings wie "$2,129.1468284147656", "$10,948.3742933", "$1,0908". Verstümmelt die Schnur.
Eugene Gr. Philippov

Ja, ich habe es nicht bemerkt. Sie haben die ans auch gegeben.
Vanjith
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.