Formatação de moeda no Python

156

Estou olhando para formatar um número como 188518982.18 a £ 188.518.982,18 usando Python.

Como posso fazer isso?

RailsSon
fonte
Você fez uma excelente observação em um comentário abaixo, @RailsSon: deseja imprimir £ s para exibir uma moeda específica, mas use essa exibição usando uma expressão japonesa para números financeiros. Acho estranho que sua solicitação não tenha sido implementada no idioma, dissociando o localeuso do valor da moeda do módulo e as propriedades de exibição dessa moeda.
Droogans

Respostas:

212

Veja o módulo de localidade .

Isso faz a formatação de moeda (e data).

>>> 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
fonte
15
Como formatar uma moeda não nativa corretamente, digamos que estou mostrando um custo em libras GB para um relatório em idioma japonês?
SingleNegationElimination
2
@TokenMacGuy: Essa é uma pergunta complicada. Relatório japonês significa regras de vírgula e casas decimais japonesas, mas o símbolo da moeda libra esterlina - não é trivialmente suportado pela Localidade. Você precisa criar uma definição de localidade personalizada.
284 S.Lott
se o número do doador for negativo, retornará o valor entre "()" por que?
Panchicore 24/10/09
6
Isso ainda não funcionou para mim, mas eu mudei para locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')e funcionou perfeitamente!
Furbeenator
2
@panchicore a notação para números negativos, conforme indicada entre parênteses, é uma prática comum no mundo da contabilidade. Experimente no oocalc ou excel e formate os números para o tipo de contabilidade.
Droogans
94

Novo no 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
fonte
6
Isso é legal, mas realmente não responde à pergunta, pois a solução solicitada inclui um símbolo de moeda e você também está codificando o número de dígitos após o decimal, que é específico da localidade. Existem muitos outros motivos para usar a resposta de localidade aceita, se você não deseja apenas o posicionamento de vírgula.
Mrooney 24/06
6
@mrooney Há também muitos motivos para não usar a resposta de localidade aceita, como não importar um módulo inteiro.
31414 Josh
1
@ Josh, "da moeda de importação local".
Andrew H
5
@mrooney: Você pode simplesmente fazer: '$ {: 0, .2f}'. formato (184467616.1), e agora você tem o símbolo
triunenature
@triunenature que resultaria em $ 123,456.78algumas vezes. Edit: markdown retira os espaços extras, finja que há mais entre $ e números #
CyberJacob
48

Não sei ao certo por que não foi mencionado mais online (ou neste tópico), mas o pacote Babel (e os utilitários Django) do pessoal do Edgewall é incrível para formatação de moeda (e muitas outras tarefas do i18n). É bom porque não sofre com a necessidade de fazer tudo globalmente, como o módulo principal de localidade do Python.

O exemplo que o OP deu seria simplesmente:

>>> import babel.numbers
>>> import decimal
>>> babel.numbers.format_currency( decimal.Decimal( "188518982.18" ), "GBP" )
£188,518,982.18
glenc
fonte
2
Nota muito tardia: ao testar isso, ele não parece formatar a moeda de maneira inteligente, pois simplesmente coloca o símbolo apropriado antes do valor (formatado no que parece ser o código de idioma que você definiu, o que é razoável), independentemente de essa moeda realmente usa seu símbolo como prefixo.
kungphu
@kungphu Como assim? Veja babel.pocoo.org/en/latest/api/…
Julian
1
@ Julian Parece que o localeargumento format_currencypode ser usado para resolver isso, mas isso não estava no documento há quatro anos (quando escrevi esse comentário) ou apenas testei o código dessa resposta como está sem verificar o documento.
Kungphu
1
@kungphu Gotcha. Eu devo não estar prestando atenção à idade deste post ontem. A alteração da documentação / função parece muito provável. Felicidades!
Julian
32

Este é um post antigo, mas acabei de implementar a seguinte solução, que:

  • Não requer módulos externos
  • Não requer a criação de uma nova função
  • Pode ser feito em linha
  • Lida com várias variáveis
  • Lida com valores negativos em dólares

Código:

num1 = 4153.53
num2 = -23159.398598

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

Resultado:

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

E para o pôster original, obviamente, basta mudar $para£

elPastor
fonte
meu formato precisava de alguma personalização, mas tudo bem, porque eu pude fazer isso com esta solução.
DonkeyKong
10
Idéia legal! Com Python 3.6 e F-cordas, parece ainda mais bonita:print(f'Value is: ${value:,.2f}'.replace('$-', '-$'))
Timo Saloranta
16

Minhas configurações de localidade pareciam incompletas, então eu também procurei além desta resposta do SO e descobri:

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

Independente do SO

Só queria compartilhar aqui.

user37986
fonte
Mas para onde chamamos o def moneyfmt(value, places=2, curr='', sep=',', dp='.', pos='', neg='-', trailneg='')?
Roel
9

Se você estiver usando o OSX e ainda não tiver definido a configuração do módulo de localidade, esta primeira resposta não funcionará, você receberá o seguinte erro:

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.

Para remediar isso, você precisará usar o seguinte:

locale.setlocale(locale.LC_ALL, 'en_US')
simoes
fonte
2
locale.setlocale (locale.LC_ALL, 'en_US.UTF-8') faz por mim
alexblum 31/01
9

"{:0,.2f}".format(float(your_numeric_value))no Python 3 faz o trabalho; fornece algo como uma das seguintes linhas:

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

Se eu fosse você, usaria o BABEL: http://babel.pocoo.org/en/latest/index.html

from babel.numbers import format_decimal


format_decimal(188518982.18, locale='en_US')
Carlos
fonte
1
O módulo locale python não funcionou para mim (qualquer local que eu o defini, reclamou), mas é necessário exigir o babel e usar essa função. Vale a pena dar uma olhada nos documentos da API, pois há mais parâmetros e funções mais úteis (como para moedas:) format_currency.
Daniel W.
3

Oh, isso é uma fera interessante.

Passei um tempo considerável para acertar isso, há três problemas principais que diferem de localidade para localidade: - símbolo e direção da moeda - separador de milhar - ponto decimal

Eu escrevi minha própria implementação bastante extensa disso, que faz parte da estrutura do kiwi python, confira a fonte LGPL: ed aqui:

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

O código é um pouco específico do Linux / Glibc, mas não deve ser muito difícil de adotar no Windows ou em outros unixes.

Depois de instalá-lo, você pode fazer o seguinte:

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

O que lhe dará:

'$10.50'

ou

'10,50 kr'

Dependendo do local selecionado atualmente.

O ponto principal deste post sobre o outro é que ele funcionará com versões mais antigas do python. locale.currency foi introduzido no python 2.5.

Johan Dahlin
fonte
Tem vantagens sobre locale.currency ()?
Ali Afshar
@AliAfshar: Uma vantagem seria em 10,50 krvez de kr 10,50.
user2394284 20/02
2

#imprimir a variável 'Total:' em um formato semelhante a '9.348.237'

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

onde '{: 7, .3f}' é o número de espaços para formatar o número nesse caso, é um milhão com 3 casas decimais. Em seguida, você adiciona o '.format (zum1). O zum1 é a variável que possui o grande número para a soma de todos os números no meu programa em particular. Variável pode ser qualquer coisa que você decida usar.

Marie
fonte
1

Inspirado no código acima: 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
fonte
0

Eu vim para olhar a mesma coisa e descobri que o python-money ainda não o utilizava, mas talvez uma mistura dos dois seria boa

James Brooks
fonte
0

Um lambda para calcular dentro de uma função, com a ajuda da resposta de @ Nate

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

e depois,

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

>>> converter(-123132132.13, "$")
'-$123,132,132.13'
mu 無
fonte
A maioria dos países usa o símbolo da moeda após o valor, e não o contrário.
Jonas Byström 03/04
@ jonas Talvez seja isso que a maioria dos países faz, mas o OP tinha antes do valor, portanto, eu o tenho antes do valor na minha resposta também :)
mu 無
0

Código python simples!

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
fonte
1
Seus retorna código de cordas como "$2,129.1468284147656", "$10,948.3742933", "$1,0908". Garbles a corda.
Eugene Gr. Philippov
Sim, eu não percebi. Você deu ans também.
Vanjith