Cómo dar formato a un número como cadena de moneda en Python

En este tutorial, cubriremos cómo dar formato a un número como una cadena de moneda en Python, utilizando el método str.format() incorporado, el módulo de configuración regional y el módulo de Babel.

Introducción

Tener que formatear manualmente un número como una cadena de moneda puede ser un proceso tedioso. Es posible que solo tenga que hacer unas pocas líneas de modificaciones, sin embargo, cuando necesitamos hacer algunas conversiones, se vuelve muy tedioso.

El primer paso para automatizar este tipo de tareas requerirá una función. En este artículo, repasaremos algunos métodos que puede usar para formatear números como cadenas de moneda en Python.

Métodos para formatear números

Repasaremos tres bibliotecas y funciones alternativas que nos permiten convertir números en cadenas de moneda:

  • El módulo lugar.
  • El módulo Babel.
  • La función str.format().

El módulo locale ya está incluido en Python, sin embargo, tendremos que instalar Babel para usarlo.

Dar formato al número como cadena de moneda con configuración regional

El módulo locale ya viene preinstalado con su versión de Python.

Este paquete permite a los desarrolladores localizar sus aplicaciones. Lo que significa que no tienen que saber en qué región se ejecutará su software, simplemente pueden escribir una base de código universal que cambiará dinámicamente según la región de uso.

Inicialización de la configuración regional

Para comenzar a usar el módulo locale, primero debe configurar la configuración regional:

1
2
3
4
5
6
7
import locale 

# To use default settings, set locale to None or leave second argument blank.
print(locale.setlocale(locale.LC_ALL, ''))

# To use a specific locale (Great Britian's locale in this case)
print(locale.setlocale(locale.LC_ALL, 'en_GB'))

El código anterior producirá el siguiente resultado:

1
2
English_United States.1252
en_GB

Para obtener la lista de configuraciones regionales disponibles, puede buscarla en MS-LCID. Alternativamente, puede imprimirlo:

1
2
3
4
5
6
7
# For the Windows operating system 
for lang in locale.windows_locale.values():
        print(lang)

# For other operating systems
for lang in locale.locale_alias.values():
        print(lang)

Ejecutar cualquiera de las variantes anteriores producirá algo similar a:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
en_GB
af_ZA
sq_AL
gsw_FR
am_ET
ar_SA
ar_IQ
ar_EG
ar_LY
ar_DZ
...

Formateo de números con configuración regional

Con su configuración regional preferida, puede formatear fácilmente cadenas de números:

1
2
3
4
5
locale.setlocale(locale.LC_ALL, '')

# If you'd like groupings - set grouping to True, else set it to false or leave it out completely
print(locale.currency(12345.67, grouping=True))
print(locale.currency(12345.67))

Ejecutando el código anterior obtenemos el siguiente resultado:

1
2
$12,345.67
$12345.67

Usando el método str.format()

El siguiente método que cubriremos es el método str.format(), que tiene la ventaja de ser el más directo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
number_string = 340020.8
# This portion is responsible for grouping the number
number_commas_only = "{:,}".format(number_string)
print(number_commas_only)

# To ensure we have two decimal places
number_two_decimal = "{:.2f}".format(number_string)
print(number_two_decimal)

# Both combined along with the currency symbol(in this case $)
currency_string = "${:,.2f}".format(number_string)
print(currency_string)

Ejecutando el código anterior obtenemos el siguiente resultado:

1
2
3
340,020.8
340020.80
$340,020.80

Sin embargo, este enfoque está codificado de forma rígida, a diferencia del anterior, que puede usar para localizar el formato de forma dinámica.

Dar formato al número como cadena de moneda con Babel

Usar Babel es quizás uno de los métodos menos conocidos, sin embargo, es muy fácil de usar e intuitivo. Viene con formateo de números y monedas, así como otras tareas de internacionalización.

A diferencia del módulo locale de Python, no tienes que preocuparte por hacer ajustes a escala global.

Para instalar Babel a través de pip, ejecute el siguiente comando:

1
2
3
$ pip install Babel
...
Successfully installed Babel-2.9.0

Una vez instalado, para lograr los mismos resultados que los otros dos métodos enumerados anteriormente, simplemente puede llamar a format_currency() en una cadena:

1
2
3
4
5
import babel.numbers
number_string = 340020.8

# The three needed arguements are the number, currency and locale
babel.numbers.format_currency(number_string, "USD", locale='en_US')

Ejecutando el código anterior obtenemos el siguiente resultado:

1
$340,020.80

Para obtener la lista completa de locales disponibles:

1
2
avail_loc = babel.localedata.locale_identifiers()
print(avail_loc)

Que se parece a esto:

1
['af', 'af_NA', 'af_ZA', 'agq', 'agq_CM', 'ak', 'ak_GH', 'am', 'am_ET',...]

Búsqueda de números en cadenas y formato como moneda {#búsqueda de números en cadenas y formato como moneda}

A veces, no trabaja con entrada numérica directa, como la entrada de un usuario. Es posible que esté trabajando con una oración o con un corpus impuro más grande. Podemos usar el módulo re para filtrar a través de diferentes tipos de entrada, encontrar valores numéricos y formatearlos.

Usemos los tres enfoques anteriores para formatear la moneda en una oración:

1
2
3
4
import re
import locale
import babel.numbers
locale.setlocale(locale.LC_ALL, 'en_US')

A continuación, creamos el patrón de expresión regular necesario para que coincida con las cadenas de números:

1
2
 # This pattern is used to match any number string
 pattern = r'\d+(\.\d{1,2})?'

A continuación, aplicamos los tres métodos que hemos aprendido a la variable de cadena message:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
message = "Our current budget is 180000, we'll need 25000.67 to cover rent, then 23400.4 for food."

# re.sub() is used to substitute substrings that match a certain pattern
# with another string, in our case the return value of a lambda function
# which will return a matching currency string.
new_message_locale = re.sub(
    pattern, lambda x: locale.currency(float(x.group()), grouping=True), message
)
new_message_str = re.sub(
    pattern, lambda x: "${:,.2f}".format(float(x.group())), message
)
new_message_babel = re.sub(
    pattern,
    lambda x: babel.numbers.format_currency(float(x.group()), "USD", locale="en_US"),
    message,
)

Comparemos la salida original con la salida obtenida de los tres métodos:

1
2
3
4
print(message)
print(new_message_locale)
print(new_message_str)
print(new_message_babel)
1
2
3
4
Our current budget is 180000, we'll need 25000.67 to cover rent, then 23400.4 for food.
Our current budget is $180,000.00, we'll need $25,000.67 to cover rent, then $23,400.40 for food.
Our current budget is $180,000.00, we'll need $25,000.67 to cover rent, then $23,400.40 for food.
Our current budget is $180,000.00, we'll need $25,000.67 to cover rent, then $23,400.40 for food.

Según el método que prefiera, la longitud de este script se puede reducir. Hay ciertas limitaciones como habrás notado.

El script tal como está, no puede diferenciar entre las cadenas de números que le gustaría formatear. Sin embargo, se puede cambiar fácilmente según sus necesidades y casos de uso.

Conclusión

En este artículo, echamos un vistazo a un par de formas de convertir números en cadenas de moneda adecuadas. Hemos cubierto el método str.format(), así como los módulos locale y babel.

Finalmente, combinamos estos métodos con el módulo de expresiones regulares de Python para lograr una gama más amplia de usos. Al final, espero que hayas podido aprender algo nuevo de todo esto que pueda ayudarte a ahorrar tiempo. o.

Licensed under CC BY-NC-SA 4.0