Formatage des devises en Python

156

Je cherche à formater un nombre comme 188518982.18 à 188 518 982,18 £ en utilisant Python.

Comment puis-je faire ceci?

RailsSon
la source
Vous avez fait un excellent point dans un commentaire ci-dessous, @RailsSon: vous voulez imprimer des £ pour afficher une devise spécifique, mais utilisez cet affichage en utilisant une expression japonaise pour les chiffres financiers. Je trouve étrange que votre demande n'ait pas été implémentée dans la langue en découplant l' localeutilisation de la valeur de la devise par le module et les propriétés d'affichage de cette devise.
Droogans

Réponses:

212

Voir le module de paramètres régionaux .

Cela fait le formatage de la devise (et de la date).

>>> 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
la source
15
Comment formater correctement une devise non native, disons que j'affiche un coût en livres sterling pour un rapport en japonais?
SingleNegationElimination
2
@TokenMacGuy: C'est une question piège. Le rapport japonais signifie les règles japonaises de virgule et de décimale, mais le symbole de devise GB Pound - pas trivialement pris en charge par Locale. Vous devez créer une définition de paramètres régionaux personnalisée.
S.Lott le
si le nombre de donneur est négatif renvoie la valeur entre "()" pourquoi?
panchicore
6
Cela ne fonctionnait toujours pas pour moi, mais je l'ai changé locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')et cela a parfaitement fonctionné!
Furbeenator
2
@panchicore la notation des nombres négatifs comme indiqué par des parenthèses est une pratique courante dans le monde de la comptabilité. Essayez-le dans oocalc ou excel et formatez les nombres selon le type de comptabilité.
Droogans du
94

Nouveau dans 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
la source
6
C'est bien mais ne répond pas vraiment à la question, car la solution demandée comprendrait un symbole monétaire, et vous codez également en dur le nombre de chiffres après la décimale, qui est spécifique à la langue. Il existe de nombreuses autres raisons d'utiliser la réponse locale acceptée si vous ne voulez pas simplement placer une virgule.
mrooney
6
@mrooney Il existe également de nombreuses raisons de ne pas utiliser la réponse locale acceptée, comme par exemple ne pas importer un module entier.
Josh
1
@Josh, "à partir de la devise d'importation locale".
Andrew H du
5
@mrooney: Vous pouvez simplement faire: '$ {: 0, .2f}'. format (184467616.1), et vous avez maintenant le symbole
triunenature
@triunenature qui en résulterait $ 123,456.78parfois cependant. Edit: le démarque supprime les espaces supplémentaires, prétendez qu'il y a plus entre le $ et les nombres
CyberJacob
48

Je ne sais pas trop pourquoi cela n'est pas mentionné plus en ligne (ou sur ce fil), mais le package Babel (et les utilitaires Django) des gars d'Edgewall est génial pour le formatage des devises (et beaucoup d'autres tâches i18n). C'est bien car il ne souffre pas de la nécessité de tout faire globalement, comme le module principal de paramètres régionaux Python.

L'exemple donné par l'OP serait simplement:

>>> import babel.numbers
>>> import decimal
>>> babel.numbers.format_currency( decimal.Decimal( "188518982.18" ), "GBP" )
£188,518,982.18
Glenc
la source
2
Note très tardive: en testant cela, il ne semble pas formater intelligemment la devise, car il colle simplement le symbole approprié avant le montant (formaté dans ce qui semble être le paramètre régional que vous avez défini, ce qui est raisonnable), que cette devise soit réellement utilise son symbole comme préfixe.
kungphu
@kungphu Que voulez-vous dire? Voir babel.pocoo.org/en/latest/api
Julian
1
@Julian Il semble que l' localeargument to format_currencypuisse être utilisé pour résoudre ce problème, mais soit ce n'était pas dans la doc il y a quatre ans (quand j'ai écrit ce commentaire) ou j'ai juste testé le code de cette réponse tel quel sans vérifier la doc.
kungphu
1
@kungphu Gotcha. Je n'ai pas dû faire attention à l'âge de ce poste hier. Le changement de documentation / fonction semble très probable. À votre santé!
Julian
32

Ceci est un article ancien, mais je viens de mettre en œuvre la solution suivante qui:

  • Ne nécessite pas de modules externes
  • Ne nécessite pas la création d'une nouvelle fonction
  • Peut être fait en ligne
  • Gère plusieurs variables
  • Gère les montants négatifs en dollars

Code:

num1 = 4153.53
num2 = -23159.398598

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

Production:

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

Et pour l'affiche originale, évidemment, il suffit de changer $pour£

elPasteur
la source
mon format nécessitait une certaine personnalisation, mais ce n'est pas grave car j'ai pu le faire avec cette solution.
DonkeyKong
10
Bonne idée! Avec Python 3.6 et f-strings, c'est encore plus beau:print(f'Value is: ${value:,.2f}'.replace('$-', '-$'))
Timo Saloranta
16

Mes paramètres régionaux semblaient incomplets, donc j'avais trop regardé au-delà de cette réponse SO et trouvé:

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

Indépendant du système d'exploitation

Je voulais juste partager ici.

user37986
la source
Mais où appelons-nous le def moneyfmt(value, places=2, curr='', sep=',', dp='.', pos='', neg='-', trailneg='')?
Roel
9

Si vous utilisez OSX et que vous n'avez pas encore défini le paramètre de votre module de paramètres régionaux, cette première réponse ne fonctionnera pas, vous recevrez l'erreur suivante:

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.

Pour remédier à cela, vous devrez utiliser les éléments suivants:

locale.setlocale(locale.LC_ALL, 'en_US')
simoes
la source
2
locale.setlocale (locale.LC_ALL, 'en_US.UTF-8') fait pour moi
alexblum
9

"{:0,.2f}".format(float(your_numeric_value))dans Python 3 fait le travail; il donne quelque chose comme l'une des lignes suivantes:

10,938.29
10,899.00
10,898.99
2,328.99
Eugene Gr. Philippov
la source
6

Si j'étais vous, j'utiliserais BABEL: http://babel.pocoo.org/en/latest/index.html

from babel.numbers import format_decimal


format_decimal(188518982.18, locale='en_US')
Carlos
la source
1
Le module de localisation python ne fonctionnait pas pour moi (quelle que soit la locale que je l'ai définie, il se plaignait) mais exiger babel et utiliser cette fonction est bien. Cela vaut la peine de jeter un œil dans la documentation de l'API car il y a plus de paramètres et de fonctions plus utiles (comme pour les devises :) format_currency.
Daniel W.
3

Oh, c'est une bête intéressante.

J'ai passé beaucoup de temps à y parvenir, il y a trois problèmes principaux qui diffèrent d'une locale à l'autre: - symbole et direction de la devise - séparateur des milliers - point décimal

J'ai écrit ma propre implémentation assez étendue de ceci qui fait partie du framework kiwi python, consultez la source LGPL: ed ici:

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

Le code est légèrement spécifique à Linux / Glibc, mais ne devrait pas être trop difficile à adopter pour Windows ou d'autres Unix.

Une fois que vous l'avez installé, vous pouvez effectuer les opérations suivantes:

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

Ce qui vous donnera alors:

'$10.50'

ou

'10,50 kr'

Selon les paramètres régionaux actuellement sélectionnés.

Le point principal de cet article par rapport à l'autre est qu'il fonctionnera avec les anciennes versions de python. locale.currency a été introduit dans python 2.5.

Johan Dahlin
la source
At-il des avantages par rapport à locale.currency ()?
Ali Afshar
@AliAfshar: Un avantage serait 10,50 krau lieu de kr 10,50.
user2394284
2

#impression de la variable 'Total:' dans un format qui ressemble à ceci '9,348.237'

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

où '{: 7, .3f}' est le nombre d'espaces pour formater le nombre dans ce cas est un million avec 3 décimales. Ensuite, vous ajoutez le '.format (zum1). Le zum1 est la variable qui a le grand nombre pour la somme de tous les nombres dans mon programme particulier. La variable peut être tout ce que vous décidez d'utiliser.

Marie
la source
1

Inspiré du code ci-dessus: 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
la source
0

J'en suis venu à regarder la même chose et j'ai trouvé que l' argent python ne l'utilisait pas encore vraiment, mais peut-être qu'un mélange des deux serait bien

James Brooks
la source
0

Un lambda pour le calculer dans une fonction, avec l'aide de la réponse de @ Nate

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

puis,

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

>>> converter(-123132132.13, "$")
'-$123,132,132.13'
mu 無
la source
La plupart des pays utilisent le symbole monétaire après le montant, et non l'inverse.
Jonas Byström
@jonas C'est peut-être ce que font la plupart des pays, mais OP l'avait avant le montant, donc je l'ai aussi avant le montant dans ma réponse :)
mu 無
0

Code python simple!

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
la source
1
Vos retours de code chaînes comme "$2,129.1468284147656", "$10,948.3742933", "$1,0908". Déforme la corde.
Eugene Gr. Philippov
Oui, je n'ai pas remarqué. Vous avez également donné les ans.
Vanjith