It's a lot more than you really need, but Babel does include currencies, in the Locale currency_symbols dictionary. Some may require a little parsing, though; for example, USD is 'US$' rather than just the dollar sign, while others, like the Euro or Yuan, have no such prefix.

I believe Babel uses the CLDR as its source.

Answer from DNS on Stack Overflow
🌐
PyPI
pypi.org › project › currency-codes
currency-codes · PyPI
from currency_codes import get_all_currencies, Currency currencies: list[Currency] = get_all_currencies()
      » pip install currency-codes
    
Published   Jun 04, 2023
Version   23.6.4
Discussions

internationalization - Python currency codes into a list - Stack Overflow
I was hoping there might be an equivalent in python. And thanks to everyone who has provided an answer so far. ... @delnan thanks for the suggestion and apologies if the question was misleading. I was using the website as an example of the currencies in the ISO list rather than wanting them ... More on stackoverflow.com
🌐 stackoverflow.com
Currency classes for Python
It good thing to learn how to do stuff like this. Like you said it more leaning the process, which is good to learn all by itself self. Right now, I see 3 big problems. It only works for like 5 currencies you give me no function to tell me what they are. Ite not clear if I can add different type of currency, or how to convert from one to another IMHO And there should be a converter or a way to add USD and YEN directly. You can do something like the return is always the first currency, this will help will a+b+c. More on reddit.com
🌐 r/Python
14
22
February 20, 2025
Python - Convert currency code to its sign - Stack Overflow
I don't know of a way to obtain this list from within Python (without using subprocess). ... This doesn't do any conversion, it just prints out a mapping for a fixed set of locales. 2016-05-27T16:14:21.02Z+00:00 ... Forex-python package will convert Currency code to its sign. More on stackoverflow.com
🌐 stackoverflow.com
converting - Currency converter in Python - Code Review Stack Exchange
Pseudocode, hypothetical code, or stub code should be replaced by a concrete example. Questions seeking an explanation of someone else's code are also off-topic. Closed 10 years ago. ... I am looking for some ways to make my code simpler for this currency converter. More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
November 19, 2015
Top answer
1 of 3
2

You have too many for-loops

for i in course:
    print(i['currency'], i['rate'])

But this need also to search <cube> with attribute currency

course = soup.findAll("cube", currency=True)

course = soup.findAll("cube", {"currenc": True})

or you would have to check if item has attribute currency

for i in course:
    if 'currency' in i.attrs:
        print(i['currency'], i['rate'])

Full code:

import requests
from bs4 import BeautifulSoup

url = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml?c892a2e0fae19504ef05028330310886'

response = requests.get(url)
soup = BeautifulSoup(response.text, "lxml")

course = soup.find_all("cube", currency=True)

for i in course:
    #print(i)
    print(i['currency'], i['rate'])
2 of 3
1

try this

r = requests.get('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml?c892a2e0fae19504ef05028330310886').text
soup = BeautifulSoup(r, "lxml")
result = [{currency.get('currency'): currency.get('rate')} for currency in soup.find_all("cube", {'currency': True})]
print(result)

OUTPUT:

[{'USD': '0.9954'}, {'JPY': '142.53'}, {'BGN': '1.9558'}, {'CZK': '24.497'}, {'DKK': '7.4366'}, {'GBP': '0.87400'}, {'HUF': '403.98'}, {'PLN': '4.7143'}, {'RON': '4.9238'}, {'SEK': '10.7541'}, {'CHF': '0.9579'}, {'ISK': '138.30'}, {'NOK': '10.1985'}, {'HRK': '7.5235'}, {'TRY': '18.1923'}, {'AUD': '1.4894'}, {'BRL': '5.2279'}, {'CAD': '1.3226'}, {'CNY': '6.9787'}, {'HKD': '7.8133'}, {'IDR': '14904.67'}, {'ILS': '3.4267'}, {'INR': '79.3605'}, {'KRW': '1383.58'}, {'MXN': '20.0028'}, {'MYR': '4.5141'}, {'NZD': '1.6717'}, {'PHP': '57.111'}, {'SGD': '1.4025'}, {'THB': '36.800'}, {'ZAR': '17.6004'}]
🌐
GitHub
gist.github.com › 1141751
Tuple of currencies for Python · GitHub
August 11, 2011 - Tuple of currencies for Python. GitHub Gist: instantly share code, notes, and snippets.
🌐
PyPI
pypi.org › project › currencies
currencies · PyPI
Display money format and its filthy currencies, for all money lovers out there. These details have been verified by PyPI · Alir3z4 · These details have not been verified by PyPI · Homepage · License: GNU General Public License (GPL) (GNU GPL 3) Author: Alireza Savand · Requires: Python <4 ·
      » pip install currencies
    
Published   Dec 12, 2020
Version   2020.12.12
🌐
pytz
pythonhosted.org › quantity › money.html
4. Money — quantity 0.9 documentation
The type of period must be the same for all exchange rates held by a money converter. A money converter is created by calling MoneyConverter, giving the base currency used by this converter:
🌐
PyPI
pypi.org › project › iso4217parse
iso4217parse · PyPI
In [1]: import iso4217parse In [2]: iso4217parse.by_symbol('$MN') Out[2]: [ Currency(alpha3='CUP', code_num=192, name='Cuban peso', symbols=['₱', '$', '﹩', '$', 'dollar', 'dollars', 'Dollar', 'Dollars', '$MN', '﹩MN', '$MN'], minor=2, countries=['CU']) ] In [3]: iso4217parse.by_symbol('$') Out[3]: [...] # 35 different currencies In [4]: [c.alpha3 for c in iso4217parse.by_symbol('$')] Out[4]: ['ARS', 'AUD', 'BBD', 'BMD', 'BZD', 'SBD', 'BND', 'CAD', 'CVE', 'KYD', 'CLP', 'COP', 'CUP', 'DOP', 'FJD', 'GYD', 'HKD', 'JMD', 'LRD', 'MXN', 'NAD', 'NZD', 'SGD', 'TTD', 'USD', 'UYU', 'TWD',
      » pip install iso4217parse
    
Published   Mar 31, 2025
Version   0.6.2
Find elsewhere
🌐
GitHub
github.com › duketemon › currency_codes
GitHub - duketemon/currency_codes: Comprehensive Python package for managing currency codes across different types of assets
from currency_codes import get_all_currencies, Currency currencies: list[Currency] = get_all_currencies()
Author   duketemon
🌐
Snyk
snyk.io › advisor › pycountry › functions › pycountry.currencies
How to use the pycountry.currencies function in pycountry | Snyk
CSRF_TRUSTED_ORIGINS = [urlparse(SITE_URL).hostname] TRUST_X_FORWARDED_FOR = config.get('pretix', 'trust_x_forwarded_for', fallback=False) if config.get('pretix', 'trust_x_forwarded_proto', fallback=False): SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') PRETIX_PLUGINS_DEFAULT = config.get('pretix', 'plugins_default', fallback='pretix.plugins.sendmail,pretix.plugins.statistics,pretix.plugins.checkinlists,pretix.plugins.autocheckin') PRETIX_PLUGINS_EXCLUDE = config.get('pretix', 'plugins_exclude', fallback='').split(',') FETCH_ECB_RATES = config.getboolean('pretix', 'ecb_rates', fallback=True) DEFAULT_CURRENCY = config.get('pretix', 'currency', fallback='EUR') CURRENCIES = list(currencies) CURRENCY_PLACES = { # default is 2 'BIF': 0, 'CLP': 0, 'DJF': 0, 'GNF': 0, 'JPY': 0, 'KMF': 0, 'KRW': 0, 'MGA': 0, 'PYG': 0, 'RWF': 0, 'VND': 0, 'VUV': 0, 'XAF': 0, 'XOF': 0,
🌐
Currencyapi.com
currencyapi.com › docs › currency-list
Currency List | currencyapi Documentation
The list of all currencies that are suppored by the currencyapi API.
🌐
PyPI
pypi.org › project › ccy
Python CCY
A python module for currencies. The module compiles a dictionary of currency objects containing information useful in financial analysis. Not all currencies in the world are supported yet.
      » pip install ccy
    
Published   Mar 28, 2026
Version   2.0.0
🌐
pytz
pythonhosted.org › ccy › overview.html
Overview — ccy 0.6.1 documentation
>>> import ccy >>> p = ccy.currency_pair('eurusd') >>> p ccy_pair: EURUSD >>> p.mkt() # market convention pair ccy_pair: EURUSD >>> p = ccy.currency_pair('chfusd') >>> p ccy_pair: CHFUSD >>> p.mkt() # market convention pair ccy_pair: USDCHF ... >>> import ccy >>> ccy.cross('aud') 'AUDUSD' >>> ccy.crossover('eur') 'EUR/USD' >>> ccy.crossover('chf') 'USD/CHF' Note, the Swiss franc cross is represented as ‘USD/CHF’, while the Aussie Dollar and Euro crosses are represented with the USD as denominator. This is the market convention which is handled by the order property of a currency object.
🌐
Readthedocs
forex-python.readthedocs.io › en › latest
forex-python — forex-python 0.3.0 documentation
Free Foreign exchange rates, bitcoin prices and currency conversion. List all currency rates.
🌐
Readthedocs
quantlib-python-docs.readthedocs.io › en › latest › currencies.html
Currencies — QuantLib-Python Documentation 1.40 documentation
symbol() : Returns a string, which is a symbol often used to represent the currency in the real world. The dollar is “$” and the yen is “¥”. It should be noted that this function may return Unicode, which may cause the program to fail in Python;
🌐
PyPI
pypi.org › project › nh-currency
Client Challenge
February 16, 2018 - JavaScript is disabled in your browser · Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
Top answer
1 of 2
6

You might not have realised it yet, but all your unimplemented methods will very much look like real_to_dollar:

  • ask the user how much of the original currency he wants converted;
  • apply a specific conversion rate;
  • tell the user the result of the conversion in the desired currency.

So that should be a single function, parametrized by the elements that differ between various calls: name of the origin currency, name of the converted currency, exchange rate.

def convert_currency(from, to, rate):
    user_value = raw_input("How many {}? ".format(from))
    amount = float(user_value)
    conversion = amount * rate
    print " {} {} is equal to {} {}.".format(user_value, from, conversion, to)

Also note the use of format to simplify building a string with numbers.

You would then call it convert_currency("reais", "dollars", 0.26) or convert_currency(" dollars", "reias", 3.85).

However, having to use a bunch of ifs to know what parameters to use (like you would have used a bunch of ifs to know which function to call) is not that great and can be a burden to maintain and expand. You could use a second dictionary to map couples of currencies to exchange rates:

RATES = {
    ("BRL", "USD"): 0.26,
    ("USD", "BRL"): 3.85,
    # Expand as necessary
}

And just have to get the rate using RATES[(user_choice1, user_choice2)].

2 of 2
3

Exchange rates change every day, so your program would quickly become either obsolete or unmaintainable by having the conversion factor as a constant in the program. I suggest you to use an API (for example: http://fixer.io/).

You have a supported currencies dictionary, but you don't test if the user input is among the supported ones. This can be done with a while True: loop and then break if the user choice is ok.

I also believe that the user would be bummed for having to digit the currency abbreviation :p...

Taking those considerations in mind, here's an example code:

import requests


SUPPORTED_CURRENCIES = {
    "EUR": "European euro",
    "USD": "US dollar",
    "GBP": "Pound sterling",
    "BRL": "Brazilian real"
}


CURRENCY_CODES = {
    1: "EUR",
    2: "USD",
    3: "GBP",
    4: "BRL"
}


def get_exchange_rate(base_currency, target_currency):
    if not (base_currency in SUPPORTED_CURRENCIES.keys()):
        raise ValueError("base currency {} not supported".format(base_currency))
    if not (target_currency in SUPPORTED_CURRENCIES.keys()):
        raise ValueError("target currency {} not supported".format(target_currency))

    if base_currency == target_currency:
        return 1

    api_uri = "https://api.fixer.io/latest?base={}&symbols={}".format(base_currency, target_currency)
    api_response = requests.get(api_uri)

    if api_response.status_code == 200:
        return api_response.json()["rates"][target_currency]


if __name__ == '__main__':
    print("Welcome to Currency Converter")

    amount = float(input("Enter the amount you wish to convert: "))

    print("Choose a base currency among our supported currencies:")
    while True:
        for code, currency in CURRENCY_CODES.items():
            print("code {}: base {}".format(code, currency))
        base_currency_code = int(input("Please digit the code: "))
        if base_currency_code in CURRENCY_CODES.keys():
            break
        else:
            print("Invalid code")
    base_currency = CURRENCY_CODES[base_currency_code]

    print("Choose a target currency among our supported currencies:")
    while True:
        for code, currency in CURRENCY_CODES.items():
            print("code {}: target {}".format(code, currency))
        target_currency_code = int(input("Please digit the code: "))
        if target_currency_code in CURRENCY_CODES.keys():
            break
        else:
            print("Invalid code")
    target_currency = CURRENCY_CODES[target_currency_code]

    exchange_rate = get_exchange_rate(base_currency, target_currency)

    print("{} {} is {} {}".format(amount, base_currency, amount * exchange_rate, target_currency))

The code uses the requests library, which is awesome and I suggest you to check it out.

Top answer
1 of 1
3

Code Style Improvements

  • "Flat is better than nested". You can make an early exit in case of invalid input:

    import sys
    
    try:
        amount = float(input("Enter amount: "))
    except ValueError:
        print("Invalid input. Please enter only numbers.")
        sys.exit(1)
    

    That will allow you to remove the else: part and continue on the top-level. Or, you can let the user retry the input until it is valid

  • on the same topic of decreasing nestedness depth - add more early exists. For instance, if input currencies are invalid, throw an error and exit. Then, remove the else: and continue with your "positive case" logic on the same level. This should improve overall readability
  • define the constants, like the list of currencies, as per PEP8 - in upper case (reference)
  • put the main execution logic to under if __name__ == '__main__':
  • you can simplify if output_cur != '': with just if output_cur:
  • I'm not sure why you are importing datetime from _datetime (with underscore). I would expect the import to be from datetime import datetime
  • don't put comment for obvious parts of the code. For example, "importing required libraries" does not provide any useful information.
  • organize imports per PEP8 - stdlib libraries, then a newline, third-parties, a new line and then your "local" dependencies, all sorted alphabetically:

    from datetime import datetime
    
    from babel import numbers
    import pycountry
    import requests
    

Other High-level ideas

  • define custom exceptions. Instead of using the error_sev and error_inp functions where you print errors, define custom exceptions like InvalidCountryValueError. Throw it with your custom message inside
  • since you are posting it on github, consider organizing the project properly - add requirements.txt with the list of dependencies, add more documentation, tests - see more at Open Sourcing a Python Project the Right Way
  • on the related topic: currently, there is only one way to use your program. Consider someone who wants to use your library as an API - not going through the standard in inputs, but calling a function asking for currency rates. Thinking about your program this way may help you to re-design it a bit, apply "Extract Method" and other refactoring methods. Also, if you would try to add tests, you will quickly realize that there is no easy way to unittest the program - usually a red flag when designing clean and modular APIs

Performance notes

  • I'd use a set to keep the supported list of currencies. Since you check the input currencies to be valid with in, this should have a positive impact on performance:

    CURRENCIES = {
        'USD', 'JPY', 'BGN', 'CZK', 'DKK', 'GBP', 'HUF', 'PLN', 'RON', 'SEK', 'CHF', 'NOK', 'HRK', 'RUB', 'TRY',
        'AUD', 'BRL', 'CAD', 'CNY', 'HKD', 'IDR', 'ILS', 'INR', 'KRW', 'MXN', 'MYR', 'NZD', 'PHP', 'SGD', 'THB',
        'ZAR', 'ISK'
    }