用 Python 免费汇率 API
获取并转换汇率
学习用 Python 调用免费汇率接口,获取实时与历史数据、转换金额、验证响应,并构建更可靠的集成。
Python 免费汇率 API:实用实现路径
比较币种覆盖、更新频率、历史深度、许可、鉴权方式和免费额度。
设置超时、检查 HTTP 状态、验证 JSON 字段并处理无效币种。
参考汇率可能每日更新,并非交易级实时行情;保存时间戳与来源。
缓存时长应匹配源数据更新节奏,并保留最后一次有效结果。
如何选择免费的货币汇率接口
“免费”可能指开放公共接口,也可能只是有限额度。接入前要核对是否需要 API Key、更新频率、币种与日期覆盖、请求配额,以及许可是否适合你的用途。
| 标准 | 需要核对 | 重要原因 |
|---|---|---|
| 鉴权 | 免 Key、免费 Key 或付费 Key | 影响接入和密钥管理 |
| 时效 | 每日、每小时或盘中 | 参考价不等于成交报价 |
| 覆盖 | 币种、历史范围、基准币 | 避免后续缺少货币对 |
| 限制 | 配额、限流、署名和许可 | 决定能否用于生产 |
无需 API Key 的免费汇率接口
免 Key 接口适合原型,但仍应设置超时、缓存、合理请求频率和降级方案。Frankfurter 的官方文档说明其公共开源接口无需 API Key,并提供央行来源的日度汇率。
公共 API、免费套餐还是付费行情?
公共参考汇率 API 适合原型、报表、分析和低频价格本地化。需要注册的免费套餐可能覆盖更多币种或提高更新频率,但也带来密钥轮换和配额监控。交易、结算、合规或面向客户的报价,通常需要具有明确授权和服务等级的市场数据源。
接入前必须回答的问题
- 数据是参考价、中间价、买入价、卖出价,还是可成交报价?
- 响应日期采用哪个时区,周末和节假日如何处理?
- 能否切换基准币,还是需要在本地计算交叉汇率?
- 是否存在署名、缓存、再分发或商业使用限制?
用 requests 在 Python 中获取最新汇率
下面使用文档公开的单一货币对接口。“最新”指服务商最近发布的参考汇率,应检查响应日期和来源,不要把它当成逐笔实时行情。
from dataclasses import dataclass
from datetime import date
from decimal import Decimal, InvalidOperation
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
@dataclass(frozen=True)
class RateObservation:
observed_on: date
base: str
quote: str
rate: Decimal
def build_session() -> requests.Session:
retry = Retry(
total=4,
connect=3,
read=3,
status=3,
backoff_factor=0.5,
status_forcelist=(429, 500, 502, 503, 504),
allowed_methods=frozenset({"GET"}),
respect_retry_after_header=True,
raise_on_status=False,
)
session = requests.Session()
session.mount("https://", HTTPAdapter(max_retries=retry))
return session
def get_rate(
session: requests.Session,
base: str = "USD",
quote: str = "EUR",
) -> RateObservation:
base, quote = base.upper(), quote.upper()
if not (len(base) == len(quote) == 3 and base.isalpha() and quote.isalpha()):
raise ValueError("Currency codes must contain three letters")
url = f"https://api.frankfurter.dev/v2/rate/{base}/{quote}"
response = session.get(url, timeout=(3.05, 10))
response.raise_for_status()
data = response.json()
required = {"date", "base", "quote", "rate"}
if not required <= data.keys():
raise ValueError("Unexpected exchange-rate response")
if data["base"] != base or data["quote"] != quote:
raise ValueError("Provider returned a different currency pair")
try:
observed_on = date.fromisoformat(data["date"])
value = Decimal(str(data["rate"]))
except (TypeError, ValueError, InvalidOperation) as exc:
raise ValueError("Invalid date or exchange rate") from exc
if not value.is_finite() or value <= 0:
raise ValueError("Exchange rate must be a positive finite number")
return RateObservation(observed_on, base, quote, value)
session = build_session()
rate = get_rate(session, "USD", "EUR")
print(rate.observed_on, rate.rate)处理超时、HTTP 错误和异常 JSON
分别处理 requests.Timeout、requests.HTTPError 和 requests.JSONDecodeError。记录服务商、货币对、状态和时间,但不要泄露密钥;只对临时故障执行退避重试。
在 Python 中换算货币金额
对单一货币对响应,用金额乘以返回汇率。展示或存储金额时使用 Decimal 并明确舍入规则,同时保存原始汇率、时间戳和来源,便于审计。
from decimal import Decimal, ROUND_HALF_UP
def convert_amount(amount, rate, minor_units=2):
value = Decimal(str(amount)) * Decimal(str(rate))
quantum = Decimal("1").scaleb(-minor_units)
return value.quantize(quantum, rounding=ROUND_HALF_UP)
converted = convert_amount("125.50", rate.rate)
print(f"125.50 USD = {converted} EUR")复用 Session,只重试临时故障
共享的 requests.Session 会复用连接。适配器只对连接或读取故障、HTTP 429 和部分 5xx 响应执行有次数上限的指数退避;respect_retry_after_header=True 会遵守服务端给出的等待时间。无效币种等确定性的 4xx 错误不会重试。必须限制尝试次数,避免外部依赖故障耗尽应用工作线程。
汇率方向、交叉汇率与金额舍入
应把每个汇率定义为“1 单位基准币可兑换多少单位目标币”。如果 USD/EUR = 0.92,表示 1 美元可兑换 0.92 欧元;反向的 EUR/USD 应为 1 ÷ 0.92,不能仍写成 0.92。必须保存供应商返回的货币对方向,不能只凭一个名为 rate 的字段猜测。
假设同一观测时点的 USD/EUR = 0.9200,USD/JPY = 150.00。两组汇率都以美元为基准,因此 EUR/JPY = 150.00 ÷ 0.9200 = 163.043478…。1,250 欧元可换算为 203,804.347… 日元,再按业务规定的日元金额精度舍入。汇率可以保留更高精度,实际应付金额则按独立规则舍入;不能在每个中间步骤提前截断,也不能混用不同日期的两组汇率。
央行参考价或日度中间价可用于会计与报表,但并不是保证可成交的买价或卖价。支付或交易报价还可能包含点差、费用、时点和交易场所差异。
周末发起请求时,接口可能返回周五公布的汇率。应分别保存请求日期、源观测日期、发布时间和抓取时间,不能把沿用值重新标成当天观测。
计算过程使用 Decimal,最终金额再依据币种精度和业务规则量化;同时保留未舍入汇率与计算链,方便后续对账。
用 Python 获取历史汇率数据
历史接口通常接收日期或日期范围。请求前校验 ISO 币种代码和日期,并明确周末、节假日、缺失值及服务商修订在应用中的处理方式。
缓存汇率但不要静默返回过期数据
把来源日期和汇率一起存储,按服务商发布节奏设置过期时间,并向调用方明确标记陈旧状态。生产环境应监控失败,并保留带明确年龄的最后有效值。
构建不隐藏缺口的汇率时间序列
应使用服务商返回的日期作为观测键,不要用请求时间替代。对缺失日期进行明确记录,或清楚说明向前填充规则。比较不同数据源前,需要统一基准币、时区、小数精度和节假日日历,再计算收益率或平均值。
Python 汇率集成的生产检查清单
HTTP 200 只代表请求成功。汇率进入定价或报表逻辑前,生产代码还应验证响应结构、货币对、来源日期、数值范围、缓存年龄和服务商身份。
拒绝缺失字段、非数字汇率、意外的基准币或目标币、不合理数值,以及时间戳倒退的数据。
将网络请求、格式标准化、业务换算、舍入和展示拆成独立函数,便于分别测试。
把供应商 JSON 统一为 dataclass 或经过校验的数据模型,至少包含基准币、目标币、Decimal 汇率、观测日期、抓取时间、来源和陈旧状态。下游代码不应依赖供应商原始字段名。
记录请求延迟、状态码类别、配额响应头、缓存命中、数据年龄、重试和降级使用情况。
连续失败后启用熔断,并明确调用方收到的是标有数据年龄的最后有效汇率,还是不可用结果。切换供应商时不得隐藏新的来源和汇率口径。
从密钥管理服务或环境变量读取 API Key,禁止写入源码、日志、浏览器代码或异常消息。
值得自动化的测试用例
- 使用固定样本测试最新与历史汇率的正常响应。
- 测试超时、连接重置、429、500、异常 JSON 和缺失字段。
- 测试不支持的币种、同币种换算、零金额和负金额。
- 测试周末日期、陈旧缓存、服务商日期变化及不同最小货币单位的舍入。
QVeris 如何帮助 Python 应用查找汇率能力
QVeris 帮助开发者和 Agent 在调用前发现并检查可用能力。你可以通过 QVeris 工具详情筛选相关金融数据工具,再逐一核对服务商文档、许可、时效和限制。
- 按任务发现汇率与货币数据能力。
- 接入前检查输入、输出和调用要求。
- 区分服务商声明与应用自身的可靠性验证。
Python 免费汇率 API 常见问题
Python 有免费的汇率 API 吗?
有。Python 可以调用开放或提供免费额度的 REST API。选择前比较密钥、配额、时效、币种、历史数据和许可。
Python 如何获取实时汇率?
发送带超时的 GET 请求,检查 HTTP 状态,解析并验证 JSON,再按数据源更新周期缓存。注意“实时”可能只是最新参考价。
哪里可以免费获取历史汇率?
部分服务提供免费的历史日度汇率,但日期范围、币种、署名和配额不同,应查看当前官方文档。
免费汇率接口需要 API Key 吗?
不一定。有的公共接口免 Key,有的免费套餐需要注册。免 Key 也不代表没有合理使用或限流规则。
