Get current exchange rate.

    :param base: A base currency
    :param target: Convert to the target currency
    :param error_log: A callable function to track the exception

    It parses current exchange rate from these services:

        1) Yahoo finance
        2) fixer.io
        3) European Central Bank

    It will fallback to the next service when previous not available.
    The exchane rate is a decimal number. If `None` is returned, it means
    the parsing goes wrong::

        >>> import exchange
        >>> exchange.rate('USD', 'CNY')
        Decimal('6.2045')

def rate(base, target, error_log=None):
    """Get current exchange rate.

    :param base: A base currency
    :param target: Convert to the target currency
    :param error_log: A callable function to track the exception

    It parses current exchange rate from these services:

        1) Yahoo finance
        2) fixer.io
        3) European Central Bank

    It will fallback to the next service when previous not available.
    The exchane rate is a decimal number. If `None` is returned, it means
    the parsing goes wrong::

        >>> import exchange
        >>> exchange.rate('USD', 'CNY')
        Decimal('6.2045')
    """
    if base == target:
        return decimal.Decimal(1.00)

    services = [yahoo, fixer, ecb]
    if error_log is None:
        error_log = _error_log

    for fn in services:
        try:
            return fn(base, target)
        except Exception as e:
            error_log(e)
    return None