> Source: https://ashareapi.com/docs/guides/python-sdk/  ·  Markdown version for LLMs / AI agents

教程

# 用 Python SDK 获取 A 股数据：pip install ashareapi
 官方 SDK 已发布：`pip install ashareapi`。5 个免费端点无需 Key，返回 pandas DataFrame（没装 pandas 就返回 `list[dict]`）；代码格式随便写；出错时 5 类异常分别告诉你该做什么。

## 安装

 bash
```
pip install ashareapi # 基础：返回 list[dict]
pip install "ashareapi[pandas]" # 加 DataFrame 支持（推荐）
```

-
 要求 Python **3.9+**；强依赖只有 `requests`，**pandas 是可选的**

-
 没装 pandas 时所有方法自动返回 `list[dict]` —— 不会因为缺依赖而报错

## 30 秒上手（免费端点不需要 Key）
 5 个免费端点：`quote` / `kline` / `hot` / `market_overview` / `changedist` —— **无需注册、无需 Key**，装上就能调。

 Python（可直接运行）
```
from ashareapi import AShareAPI

cli = AShareAPI() # 免费端点无需 Key
df = cli.quote("sh600667") # 实时行情 → DataFrame
print(df[["date", "last", "turnover"]])

print(cli.kline("600667.SH", count=5)) # 代码格式随便写（自动归一化）
print(cli.hot(limit=10)) # 热搜榜
print(cli.changedist()) # 涨跌分布（市场广度）
```

## 代码格式：三种写法都认
 写 `cli.quote("600667.SH")` 和 `cli.quote("sh600667")` 是**同一件事** —— 从别的数据源迁过来的代码不用改。
 |
| | 你写的 | 会被归一化为 | 说明

| | `sh600667` | `sh600667` | 原生格式（市场前缀 + 代码）

| | `600667.SH` | `sh600667` | 常见后缀写法，自动转换

| | `600667` | `sh600667` | 纯 6 位按首位推断：5/6 → 沪、0/3 → 深、4/8 → 北

 `sh600667`
 `sh600667`
 原生格式（市场前缀 + 代码）

 `600667.SH`
 `sh600667`
 常见后缀写法，自动转换

 `600667`
 `sh600667`
 纯 6 位按首位推断：5/6 → 沪、0/3 → 深、4/8 → 北

## 付费端点：带 Key 调用

 Python
```
from ashareapi import AShareAPI

cli = AShareAPI("ct-你的Key") # 或设环境变量 ASHARE_API_KEY
df = cli.screen(preset="low_pe", orderby="ROETTM", limit=10)
print(df.head())

print(cli.fund("sh600667")) # 资金流 + 龙虎榜 + 大宗 + 两融
print(cli.finance("sh600667")) # 三大报表
print(cli.lhb("institution")) # 龙虎榜机构榜
```

-
 Key 从 [定价页](https://ashareapi.com/pricing/) 获取（¥9.9 起）

-
 32 个端点 = 32 个方法，命名与端点一一对应（`/v1/margin-trade` → `margin_trade()`）

-
 完整清单见 [端点文档](https://ashareapi.com/endpoints/)

## 返回形态：DataFrame 还是 list？
 SDK 把**对象数组**转成 DataFrame（优先取 `structured`，没有则取 `data`）；**表列表**（`finance`）与**多段结构**（`shareholder` / `calendar`）**原样返回**（不硬套 DataFrame，避免退化成 3×1 的怪表）；`raw=True` 可拿完整信封。
 |
| | 环境 | 返回 | 用法

| | 装了 pandas（`ashareapi[pandas]`） | `pandas.DataFrame` | 直接 `df.head()` / `df[["date","last"]]` / 画图

| | 没装 pandas | `list[dict]` | 自己遍历 —— **同样的代码不会崩**

 装了 pandas（`ashareapi[pandas]`）
 `pandas.DataFrame`
 直接 `df.head()` / `df[["date","last"]]` / 画图

 没装 pandas
 `list[dict]`
 自己遍历 —— **同样的代码不会崩**

## 错误处理：5 类异常各说各的

 Python
```
from ashareapi import (AShareAPI, AuthError, RateLimitError,
 UpstreamError, EmptyResultError)

cli = AShareAPI()
try:
 df = cli.fund("sh600667")
except AuthError as e: # 401 → 这是付费端点，去拿 Key
 print(e)
except RateLimitError as e: # 429 → 降频 / 解一次 PoW 提额 / 升级档位
 print(e)
except UpstreamError as e: # 上游取数失败（已自动换源、不扣次数）→ 重试一次
 print(e)
except EmptyResultError as e: # 当前无数据（如当天无大宗交易）→ 不计费，换条件
 print(e)
```
 |
| | 异常 | 什么时候抛 | 你该做什么

| | `AuthError` | 401 / 缺 Key 调了付费端点 | 去拿 Key，或改用免费端点

| | `RateLimitError` | 429 超出档位频率 | 降频；或解 PoW 挑战提额；或升级

| | `UpstreamError` | 上游取数失败（已自动换源、**不扣次数**） | 重试一次通常就好

| | `EmptyResultError` | 请求成功但**当前无数据**（如当天无大宗交易） | 换条件或稍后再试，**不计费**

| | `APIError` | 其他（网络 / 5xx 重试耗尽） | 看异常信息

 `AuthError`
 401 / 缺 Key 调了付费端点
 去拿 Key，或改用免费端点

 `RateLimitError`
 429 超出档位频率
 降频；或解 PoW 挑战提额；或升级

 `UpstreamError`
 上游取数失败（已自动换源、**不扣次数**）
 重试一次通常就好

 `EmptyResultError`
 请求成功但**当前无数据**（如当天无大宗交易）
 换条件或稍后再试，**不计费**

 `APIError`
 其他（网络 / 5xx 重试耗尽）
 看异常信息

## SDK vs 直接调 HTTP vs Tushare / AkShare
 |
| | | ashareapi SDK | 自己 requests | Tushare | AkShare

| | 上手成本 | **pip 装完即用** | 自己封装重试/异常 | 注册 + 积分门槛 | 装完即用

| | 返回形态 | **DataFrame**（无 pandas 降级 list） | 自己解析 JSON | DataFrame | DataFrame

| | 免费试用 | **5 个端点免 Key** | 同样免 Key | 需注册（有积分门槛） | 免费

| | 错误处理 | **5 类异常**（含"无数据≠失败"） | 自己判断 | 看返回值 | 自己判断

| | 维护 | **我们维护**（多源自动切换） | 上游改了你改 | 官方维护 | 上游改版常需跟进

 上手成本
 **pip 装完即用**
 自己封装重试/异常
 注册 + 积分门槛
 装完即用

 返回形态
 **DataFrame**（无 pandas 降级 list）
 自己解析 JSON
 DataFrame
 DataFrame

 免费试用
 **5 个端点免 Key**
 同样免 Key
 需注册（有积分门槛）
 免费

 错误处理
 **5 类异常**（含"无数据≠失败"）
 自己判断
 看返回值
 自己判断

 维护
 **我们维护**（多源自动切换）
 上游改了你改
 官方维护
 上游改版常需跟进

## 常见错误与边界

-
 `401` 调付费端点 → 没带 Key：免费端点只有 5 个，其余需要 Key

-
 `429` → 匿名限额较低；解一次 PoW（`cli.challenge()`）可提到 60 次/分，或升级档位

-
 **`EmptyResultError` 不是失败**：是"当前确实没有这类数据"（例如当天没有大宗交易）—— 不计费，别当异常处理

-
 **数据日期**：休市日不会变成"今天"，看返回里的 `date` 字段判断数据属于哪个交易日

-
 **单位**：`volume` 是手（×100 = 股）· `amount` 是元 · 比率字段是百分数（`20` = 20%）

-
 **分钟级 K 线**：当前只提供日/周/月，分钟级不在范围内（明写，别猜）

## 常见问题
 SDK 免费吗？
 **SDK 本身免费（MIT 开源）**，5 个免费端点（行情 / K线 / 热搜 / 市场总览 / 涨跌分布）**无需 Key、无需注册**即可调用。其余 25 个端点需要 API Key（¥9.9 起），SDK 不额外收费。

 必须装 pandas 吗？
 不必须。pandas 是**可选依赖**：装了返回 `DataFrame`（推荐），没装自动返回 `list[dict]`，代码不会崩。用 `pip install "ashareapi[pandas]"` 一起装。

 为什么我写 600667.SH 也能用？
 SDK 内置代码归一化：`sh600667`、`600667.SH`、`600667` 三种写法都接受，会统一转成 `sh600667` 再请求。纯 6 位按首位推断市场（5/6 → 沪、0/3 → 深、4/8 → 北）。

 EmptyResultError 和 UpstreamError 有什么区别？
 **EmptyResultError = 当前没有这类数据**（例如当天没有大宗交易）——请求是成功的、**不计费**，换条件或稍后再试即可。**UpstreamError = 上游取数失败**（我们已自动换源、同样不扣次数），重试一次通常就好。分开是为了让你一眼知道"该换条件"还是"该重试"。

 怎么升级 SDK？
 `pip install -U ashareapi`。最新版本与全部变更见 [更新日志](/changelog)。

 最后更新: 2026-09-23
 代码与返回形态取自 SDK 的真实运行结果（2026-09-23 从 PyPI 安装验证：quote 30 行 / hot 3 行 / 匿名限流时正确抛 RateLimitError）。Tushare、AkShare 的描述依据其官方文档，其接口与门槛由对方变更。

 接着看

-
[端点文档（32 个端点的字段与示例）](/endpoints)

-
[Node.js / TypeScript 版 SDK（npm install ashareapi）](/docs/guides/nodejs-ashare-quotes)

-
[用 Python 获取实时行情：3 种方法对比](/docs/guides/python-ashare-quotes)

-
[从 Tushare 迁移（接口对照 + 代码改写）](/docs/migrate-from-tushare)

-
[错误码表](/docs/errors)

 [← 全部教程](/docs/guides)
