Skip to main content

perexchange

perexchange fetches live PEN/USD rates from Peruvian exchange houses.

Requires Python 3.10 or later.

Install

python -m pip install perexchange

Fetch rates

fetch_rates() runs the selected source adapters concurrently and returns the rates that were fetched successfully:

import asyncio

import perexchange


async def main() -> None:
    rates = await perexchange.fetch_rates(sources=["cambiafx", "tucambista"])
    for rate in rates:
        print(rate.source, rate.name, rate.buy_price, rate.sell_price)


asyncio.run(main())

With no sources argument, all registered sources are queried. Source names are matched without regard to case, accents, spaces, or punctuation. kambioonline2 is an alias for kambioonline.

An unknown or repeated source raises ConfigurationError before any request starts. Invalid timeout and retry settings raise the same exception.

Fetch settings

async def fetch_rates(
    sources: Sequence[str] | None = None,
    *,
    timeout: float = 10.0,
    max_attempts: int = 3,
    total_timeout: float | None = 30.0,
    client: httpx.AsyncClient | None = None,
) -> list[ExchangeRate]:
  • timeout limits each HTTP request.
  • max_attempts is the total number of attempts for each source, including the first.
  • total_timeout limits one source operation, including retries and backoff. Set it to None to disable that limit.
  • Transport errors and 408, 429, and 5xx responses are retried. Other 4xx responses and parse errors are not.
  • A numeric Retry-After value for 429 is honored up to 30 seconds.
  • If you pass a client, perexchange leaves it open. Otherwise it creates and closes a client for the call.

Some sources need more than one request. One attempt repeats that source's full operation.

Failures

fetch_rates() leaves sources that fail out of its result. Use fetch_rates_report() when the caller needs to distinguish an empty result from sources that failed:

report = await perexchange.fetch_rates_report()

for failure in report.failures:
    print(f"{failure.source}: {failure.message}")

Expected network, timeout, and parse failures are recorded in report.failures. Other exceptions are raised so programming errors are not hidden.

ConfigurationError is available from the top-level perexchange module for callers that need to catch invalid source selections or fetch settings.

Results keep source selection order. A repeated (source, name) pair keeps its first value. The aggregator's rows for sources with a dedicated adapter are removed from the final result.

Version 2.0 changes

  • ExchangeRate requires a source field.
  • fetch_rates() and fetch_rates_report() use sources instead of houses.
  • max_retries is now max_attempts.
  • Source failures are available through fetch_rates_report().

ExchangeRate

ExchangeRate is an immutable dataclass with these fields:

  • source: the stable source ID, such as cambiafx.
  • name: the display name returned by the source. It can include a quote tier such as tkambio_5000.
  • buy_price: PEN needed to buy one USD.
  • sell_price: PEN received for selling one USD.
  • timestamp: a timezone-aware datetime from the source or the time of the fetch.

The spread property is sell_price - buy_price.

Metadata

Release files for perexchange 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for perexchange 2.0.0
File Size Uploaded
perexchange-2.0.0.tar.gz 22.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for perexchange 2.0.0
File Interpreter ABI Platform
perexchange-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 59.0 kB

Release files / perexchange-2.0.0.tar.gz

Download URL perexchange-2.0.0.tar.gz
Size 22.2 kB
Tags Source
SHA-256 checksum
How to use checksums
809895af2ea97076ce81eb4e70c7da3f106c1754793cef78776183dd042fce62
BLAKE2b-256 checksum
How to use checksums
141566858592dd8abf13a063f6dc6d47cd379a28cb09a6975a35f864a9704e35
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.

Transparency log

Release files / perexchange-2.0.0-py3-none-any.whl

Download URL perexchange-2.0.0-py3-none-any.whl
Size 36.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e57e8b0561c5b7ee1035106e6a054bd9492153b0ad1f26993525b390b20abcdf
BLAKE2b-256 checksum
How to use checksums
25e0e6447f72b1f43c430660ded1dad6bc294329bab9a7d6bacdd68fbd041e74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page