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 OverflowIt'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.
import locale
locales=('en_AG', 'en_AU.utf8', 'en_BW.utf8', 'en_CA.utf8',
'en_DK.utf8', 'en_GB.utf8', 'en_HK.utf8', 'en_IE.utf8', 'en_IN', 'en_NG',
'en_NZ.utf8', 'en_PH.utf8', 'en_SG.utf8', 'en_US.utf8', 'en_ZA.utf8',
'en_ZW.utf8', 'ja_JP.utf8')
for l in locales:
locale.setlocale(locale.LC_ALL, l)
conv=locale.localeconv()
print('{int_curr_symbol} ==> {currency_symbol}'.format(**conv))
# XCD ==> $
# AUD ==> $
# BWP ==> Pu
# CAD ==> $
# DKK ==> kr
# GBP ==> £
# HKD ==> HK$
# EUR ==> €
# INR ==> ₨
# NGN ==> ₦
# NZD ==> $
# PHP ==> Php
# SGD ==> $
# USD ==> $
# ZAR ==> R
# ZWD ==> Z$
# JPY ==> ¥
This depends on what locales are installed on your machine. On *nix machines, you can find out what locales are available with the command locale -a.
» pip install currency-codes
internationalization - Python currency codes into a list - Stack Overflow
Currency classes for Python
Python - Convert currency code to its sign - Stack Overflow
converting - Currency converter in Python - Code Review Stack Exchange
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'])
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'}]
» pip install currencies
Not very elegant or nifty, but you can generate the list once and save to use it later:
import urllib, re
url = "http://www.iso.org/iso/support/faqs/faqs_widely_used_standards/widely_used_standards_other/currency_codes/currency_codes_list-1.htm"
print re.findall(r'\<td valign\="top"\>\s+([A-WYZ][A-Z]{2})\s+\</td\>', urllib.urlopen(url).read())
output:
['AFN', 'EUR', 'ALL', 'DZD', 'USD', 'EUR', 'AOA', 'ARS', 'AMD', 'AWG', 'AUD',
...
'UZS', 'VUV', 'EUR', 'VEF', 'VND', 'USD', 'USD', 'MAD', 'YER', 'ZMK', 'ZWL', 'SDR']
Note that you'll need to prune everything after X.. as they are apparently reserved names, which means that you'll get one rogue entry (SDR, the last element) which you can just delete by yourself.
You can get currency codes (and other) data from geonames. Here's some code that downloads the data (save the file locally to achieve the same result offline) and populates a list:
import urllib2
data = urllib2.urlopen('http://download.geonames.org/export/dump/countryInfo.txt')
ccodes = []
for line in data.read().split('\n'):
if not line.startswith('#'):
line = line.split('\t')
try:
if line[10]:
ccodes.append(line[10])
except IndexError:
pass
ccodes = list(set(ccodes))
ccodes.sort()
» pip install iso4217parse
» pip install ccy
Monepy
A python package that implements currency classes to work with monetary values.
Target audience
I created it mostly for some data analysis tasks I usually do, and also as way to learn about project structure, documentation, github actions and how to publish packages.
I wouldn't know if it's production ready.
Comparison
After starting it I found about py-moneyed. They are quite similar, but I wanted something that looks "cleaner" when using it.
Any feedback will be appreciated.
How about Babel?
from babel import numbers
print numbers.get_currency_symbol('USD', locale='en') # => $1,500.00
print numbers.get_currency_symbol('GBP', locale='fr_FR') # => 1 500,00 £UK
Using the locale module:
import locale
locales=('en_AU.utf8', 'en_BW.utf8', 'en_CA.utf8',
'en_DK.utf8', 'en_GB.utf8', 'en_HK.utf8', 'en_IE.utf8', 'en_IN', 'en_NG',
'en_PH.utf8', 'en_US.utf8', 'en_ZA.utf8',
'en_ZW.utf8', 'ja_JP.utf8')
for l in locales:
locale.setlocale(locale.LC_ALL, l)
conv=locale.localeconv()
print('{ics} ==> {s}'.format(ics=conv['int_curr_symbol'],
s=conv['currency_symbol']))
yields:
AUD ==> $
BWP ==> Pu
CAD ==> $
DKK ==> kr
GBP ==> £
HKD ==> HK$
EUR ==> €
INR ==> ₨
NGN ==> ₦
PHP ==> Php
USD ==> $
ZAR ==> R
ZWD ==> Z$
JPY ==> ¥
Note you need the locale information installed on your machine. On Ubuntu, this means having the right language-pack-* packages installed.
On *nix systems, you can find the list of known locales (e.g. en_GB.utf8) with
locale -a
I don't know of a way to obtain this list from within Python (without using subprocess).
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)].
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.