OpenAI的Python库设计启示 | AI生成和翻译

Home 2025.09

以下是 openai/openai-python 的快速解析,以及你可以借鉴的构建优秀 Python 库的经验。

仓库概览

可复用的设计要点

可复用的基础结构

yourlib/
  pyproject.toml
  noxfile.py
  mypy.ini
  README.md
  CHANGELOG.md
  SECURITY.md
  src/yourlib/
    __init__.py
    _version.py
    _types.py            # TypedDicts, enums
    _errors.py           # Exception hierarchy
    _http.py             # httpx client wrapper, retries, timeouts
    _pagination.py       # generic Pager[T]
    client.py            # Client + AsyncClient, auth, base URL
    resources/
      __init__.py
      widgets.py         # resource groups w/ sync+async methods
    streaming.py         # SSE helpers (sync/async)
  tests/
    test_client.py
    test_widgets.py
  examples/
    quickstart.py
    async_quickstart.py

公共 API (src/yourlib/__init__.py)

from .client import Client, AsyncClient
from ._errors import YourLibError, APIError, RateLimitError
__all__ = ["Client", "AsyncClient", "YourLibError", "APIError", "RateLimitError"]

客户端结构(同步与异步)

# src/yourlib/client.py
import httpx
from .resources.widgets import Widgets
from ._http import HttpTransport

class Client:
    def __init__(self, api_key=None, base_url="https://api.example.com", http_client=None):
        self._transport = HttpTransport(api_key, base_url, http_client or httpx.Client(timeout=30))
        self.widgets = Widgets(self._transport)

class AsyncClient:
    def __init__(self, api_key=None, base_url="https://api.example.com", http_client=None):
        self._transport = HttpTransport(api_key, base_url, http_client or httpx.AsyncClient(timeout=30))
        self.widgets = Widgets(self._transport)

分页模式

# src/yourlib/_pagination.py
from typing import AsyncIterator, Iterator, Generic, TypeVar, Callable, Optional
T = TypeVar("T")
class Pager(Generic[T]):
    def __init__(self, fetch: Callable[..., dict], limit: int = 100):
        self._fetch = fetch
        self._limit = limit
        self._cursor = None
    def __iter__(self) -> Iterator[T]:
        while True:
            page = self._fetch(limit=self._limit, cursor=self._cursor)
            for item in page["data"]:
                yield item
            self._cursor = page.get("next_cursor")
            if not self._cursor:
                break

通过此实现,用户可使用 for item in client.widgets.list(limit=50): ...。OpenAI SDK 采用了相同方法。(GitHub

流式处理模式(SSE)

可扩展的工具链与发布流程

文档与示例

错误、重试与超时(需实现的内容)

打包与兼容性

需避免的陷阱

如果需要,我可以为具体领域搭建此结构(例如为内部 REST 服务构建类型化客户端,支持同步/异步、分页和流式处理),并提供可直接运行的 nox、CI 和示例脚本。


Back Donate