在Python中将数字格式化为货币形式

12

我从Python中的货币格式化学到,可以使用locale模块将数字格式化为货币。例如,

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import locale

value = 123456789

l = locale.setlocale(locale.LC_ALL, '')     # LC_CTYPE=en_US.UTF-8;LC_NUMERIC=fr_FR.UTF-8;LC_TIME=fr_FR.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=fr_FR.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=fr_FR.UTF-8;LC_NAME=fr_FR.UTF-8;LC_ADDRESS=fr_FR.UTF-8;LC_TELEPHONE=fr_FR.UTF-8;LC_MEASUREMENT=fr_FR.UTF-8;LC_IDENTIFICATION=fr_FR.UTF-8
s = locale.currency(value, grouping=True)   # 123 456 789,00 €

locale.setlocale(locale.LC_ALL, 'en_US.utf-8') 
s = locale.currency(value, grouping=True)   # $123,456,789.00

locale.setlocale(locale.LC_ALL, 'en_US')    # WHY? locale.Error: unsupported locale setting
s = locale.currency(value, grouping=True)

我想将数字格式化为其他货币,比如de_DE。但我遇到了一个问题:locale.Error: unsupported locale setting,因为de_DE不在locale -a列表中。

locale.setlocale(locale.LC_ALL, 'de_DE')        # locale.Error: unsupported locale setting
s = locale.currency(value, grouping=True)

一个解决方法是将此区域设置添加到我的计算机中。还有更好的方法吗?

3个回答

10

babel.numbers

In [22]: from babel.numbers import format_decimal
In [23]:  format_decimal(12345, locale='de_DE')
Out[23]: u'12.345'

In [24]: format_decimal(1.2345, locale='sv_SE')
Out[24]: u'1,234'

或者在您的情况下,format_currency函数:

In [7]: from babel.numbers import format_currency

In [8]: print format_currency(1099.98, 'USD', locale='en_US')
$1,099.98

In [9]: print format_currency(1099.98, 'USD', locale='es_CO')
1.099,98 US$

In [10]: print format_currency(1099.98, 'EUR', locale='de_DE')
1.099,98 €

1
我知道如果你传递了区域设置,你可以在不使用美元符号的情况下解析,但是对于 $123,456,789.00 我不确定如何处理或者是否能够处理。请参考 http://babel.pocoo.org/en/latest/numbers.html#parsing-numbers。 - Padraic Cunningham
谢谢。要求提出一个新问题是不公平的。因此,我提出了一个新问题,在Python中将货币格式化为数字 - SparkAndShine
1
没问题,我有一个解析器的想法,可以适用于任何货币。如果有一个好的库已经存在,我会通知你的。 - Padraic Cunningham
非常感谢。不幸的是,在Python中将本地货币格式化为数字被标记为重复。我认为它不是重复的。 - SparkAndShine
1
我重新打开了这个问题,因为它绝对不是重复的,从格式化的货币字符串返回到十进制数还有很多要做的工作。 - Padraic Cunningham
显示剩余2条评论

4

对于那些希望以类似于货币格式的方式格式化数字的人,可以使用 locale.format_string 函数进行格式化。

value = 123456789

import locale
locale.setlocale(locale.LC_ALL, 'de_DE') 
print(locale.format_string('%.2f', value, True))

将返回

123.456.789,00

这似乎在Python 3.7.6上无法工作。我使用了包babel和format_number。 - squarism
它适用于Python 3.9和3.10,但您可能需要将区域设置添加到您的操作系统中。在基于Debian的系统上,可以使用sudo dpkg-reconfigure locales命令(来源:https://dev59.com/S1oV5IYBdhLWcg3wVNeZ#43203667)。 - ksyrium

1

我知道有两种解决方案:

Babel

Babel是最好的解决方案,因为您可以选择任何货币,而不受区域设置的限制。

缺点是文档记录不足。要了解所有选项,您必须阅读Babel源代码以使用所需的函数。

安装Babel:

$ pip install Babel

使用方法:

import babel.numbers

amount = 123456789.123

print(babel.numbers.format_currency(amount, 'EUR', locale='fr_CA'))
# 123 456 789,12 €

print(babel.numbers.format_currency(amount, 'EUR', locale='en_CA'))
# €123,456,789.12

print(babel.numbers.format_currency(amount, '', locale='en_CA'))
# 123,456,789.12

localize.currency()

locale.currency() 的一个限制是它假定与区域设置相匹配的货币。例如,en_US => $/USDfr_FR => €/EUR。因此,如果显示的货币与区域设置不匹配,您可能需要使用 String.replace() 方法替换货币符号。

根据区域设置,例如 en_USen_GBfr_FRfr_CA,它将知道:

  • 使用哪个小数分隔符(例如 100.00 vs 100,00
  • 使用哪个千位分隔符(例如 1,000 vs 1.000
  • 使用哪个货币符号(例如 $100 vs €100USD 100 vs EUR 100
  • 在哪里放置货币符号(例如 $100 vs 100 $
import locale

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

amount = 123456789.123
grouping = True  # thousands separator

# '123.456.789,12 Eu'
locale.currency(amount, symbol=True, grouping=True, international=False)

# '123.456.789,12 EUR'
locale.currency(amount, symbol=True, grouping=True, international=False)

# '123.456,789'
locale.currency(amount, symbol=False, grouping=True)

# '123456,789'
locale.currency(amount, symbol=False, grouping=True)

可选的参数如下

# which currency symbol to use, and where to place it
symbol=True and international=True # => 'USD 100.00'
symbol=True and international=False # => '$100.00'
symbol=False # => '100.00'

# thousands separator
grouping = True # => '1000.00'
grouping = False # => '1,000.00'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接