نسخهی 1.0.0 از SDK پایتون Anthropic در ۲۰ اوت ۲۰۲۶ منتشر شد و لایهی HTTP آن از httpx به fork نگهداریشدهی httpx2 منتقل شد. نتیجهی عملی این است که یک کلاینت قدیمیِ httpx در لحظهی ساخت با TypeError میمیرد، ولی ابزارهایی مثل respx بیصدا از دیدن درخواستهای SDK محروم میشوند. در این نوشته هر دو حالت را روی همین ماشین اجرا میکنیم و نشان میدهیم httpx2.alias_httpx() چرا باید قبل از هر import httpx صدا زده شود. همهی خروجیها بدون کلید API و روی anthropic نسخهی 1.8.0 و httpx2 نسخهی 2.13.1 گرفته شدهاند.
چه چیزی در 1.0.0 عوض شد و چه چیزی هنوز کار میکند
یادداشت انتشار v1.0.0 فقط یک خط شکسته دارد: «client: upgrade to httpx2 and some minor breaking changes» [2]. راهنمای رسمی میگوید اگر فقط مقدار ساده به SDK بدهی، مثل timeout=30.0، به احتمال زیاد کاری برای انجام دادن نیست [1].
حداقل نسخهی پایتون از 3.9 به 3.10 رفت؛ Pydantic نسخهی 1 و 2 هر دو پشتیبانی میشوند [1]. آخرین نسخهی منتشرشده روی PyPI در لحظهی خواندن این پست 1.12.1 است [5].
جدول زیر همان چیزی است که باید از آن بیرون بیاید: کدام تغییر با صدای بلند میشکند و کدام یک بیصدا.
| تغییر | چطور خودش را نشان میدهد | راه درست |
|---|---|---|
لایهی HTTP از httpx به httpx2 | TypeError در لحظهی ساخت کلاینت، پیش از هر درخواستی | import httpx2 as httpx یا یکی از re-export های خود SDK |
ابزار رهگیری و mock روی httpx | هیچ؛ تست سبز میماند و ترافیک SDK را نمیبیند | httpx2.alias_httpx() پیش از هر import دیگر |
temperature و top_p و top_k | TypeError روی امضای متد | حذف؛ یا extra_body برای مدل قدیمی |
Text Completions و HUMAN_PROMPT | حذف شده؛ client.completions دیگر وجود ندارد | client.messages.create() |
dict اسکیمای output_format | TypeError؛ فقط کلاس پذیرفته میشود | output_config={"format": {...}} |
AnthropicBedrock بدون ناحیه | ValueError بهجای برگشت خاموش به us-east-1 | aws_region= یا متغیر AWS_REGION |
راهنمای رسمی میگوید یک بررسی نوع با pyright یا mypy تقریبا همهی این موارد را خطا نشان میدهد و به همین دلیل یک چکلیست آماده میداند [1].
خطای بلند: کلاینت قدیمی که در لحظهی ساخت میمیرد
این فایل نقطهی شروع ماست. کد روی SDK دورهی 0.x بیصدا کار میکرد و کاری جز دادن یک timeout و یک proxy به کلاینت نمیکرد؛ هر دو روی همین ماشین بازتولید شدند.
# فایل دورهی 0.x: این کد روی SDK قبلی بیصدا کار میکرد
import httpx
from anthropic import Anthropic, DefaultHttpxClient
client = Anthropic(
timeout=httpx.Timeout(60.0, connect=5.0),
http_client=DefaultHttpxClient(proxy="http://my.proxy.example"),
)
$ python3 -m pip show anthropic | head -2
Name: anthropic
Version: 1.8.0
$ grep -rn "httpx\." .
./client.py:6: timeout=httpx.Timeout(60.0, connect=5.0),
حالا اسکریپتی مینویسیم که هیچ درخواستی به شبکه نمیفرستد و فقط سازنده را میسازد. نقطهی اول، کلاینتی است که از بستهی قدیمی آمده است، و نقطهی دوم، همان کلاینت پس از یک خط alias.
# سه پرسش که به کلید API نیاز ندارند و فقط سازنده را میسازند
import anthropic, httpx, httpx2
print("anthropic", anthropic.__version__, "| httpx2", httpx2.__version__)
# ۱) خطای بلند: کلاینت از بستهی قدیمی
try:
anthropic.Anthropic(api_key="x", http_client=httpx.Client())
except TypeError as e:
print("TypeError:", e)
# ۲) بعد از alias، همان کد ساخته میشود
import httpx2 as httpx_fixed
from anthropic import DefaultHttpxClient
c = anthropic.Anthropic(
api_key="x",
timeout=httpx_fixed.Timeout(60.0, connect=5.0),
http_client=DefaultHttpxClient(proxy="http://my.proxy.example"),
)
print("ساخته شد:", type(c).__name__, "|", c.timeout)
print("SDK روی httpx2 است:", anthropic._base_client.httpx2 is httpx2)
$ python3 probe.py
anthropic 1.8.0 | httpx2 2.13.1
TypeError: Invalid `http_client` argument; `httpx.Client` is from the `httpx` package, but this SDK uses `httpx2`. Use `httpx2.Client` instead.
ساخته شد: Anthropic | Timeout(connect=5.0, read=60.0, write=60.0, pool=60.0)
SDK روی httpx2 است: True
خروجی واقعی همین اجرا روی همین ماشین است. خطای بلند در همان خطی میآید که کلاینت قدیمی داده میشود، پس کم از مهاجرت شما خبر میدهد. بعد از alias همان کد بدون تغییر دیگری ساخته میشود، و SDK روی httpx2 سوار است نه روی httpx.
راهنمای رسمی تصریح میکند که دادن یک httpx.Client از بستهی قدیمی در لحظهی ساخت TypeError میدهد، پس این مورد نمیتواند بیصدا از دست برود [1]. اگر بهجای httpx2 از re-export های خود SDK استفاده کنی، بدون آنکه یک import عوض کنی همان نتیجه را میگیری [1].
اگر پروژهی تو فقط مقدار ساده به SDK میدهد، مهاجرت تمام است و تست سبز یعنی کار درست انجام شده. خطر از جای دیگری است: ابزارهایی که خودِ بستهی httpx را patch میکنند، بعد از ارتقا بیصدا از دیدن درخواستهای SDK محروم میشوند و تستت سبز میماند در حالی که هیچ چیز آزمون نشده است.
خطر بیصدا: وقتی تست سبز است ولی هیچچیز آزمون نشده
این بدترین بخش مهاجرت است و راهنمای رسمی نام میبرد: respx، pytest-httpx، vcrpy و اینسترومنتیشن OpenTelemetry و Sentry، خودِ بستهی httpx را patch میکنند، و SDK دیگر از آن بسته استفاده نمیکند [1]. نتیجه این است که این ابزارها همچنان import میشوند و گزارش میدهند، ولی هیچ درخواستی از SDK را نمیبینند.
پس تستی که با mock نوشتهای و سبز میشود، ممکن است اصلا چیزی را نسنجیده باشد. راهنمای رسمی برای pytest یک پلاگین زودهنگام پیشنهاد میکند که پیش از هر چیز دیگر اجرا شود.
# tests/_alias_httpx.py
import httpx2
httpx2.alias_httpx() # باعث میشود import httpx به httpx2 اشاره کند
# pyproject.toml
[tool.pytest.ini_options]
addopts = "-p tests._alias_httpx"
pythonpath = ["."]
تابع alias_httpx() یک شرط ترتیبی سخت دارد که اگر رعایت نشود، خودش با RuntimeError میایستد. در فرایند تمیز امتحان کردیم که اول import httpx و بعد alias، خطا میدهد و ترتیب درست، بدون خطا رد میشود.
$ python3 order.py
=== A: httpx imported first, then alias_httpx() ===
exit: 1
RuntimeError: httpx was already imported; call `alias_httpx()` before any `import httpx`.
=== B: alias_httpx() first, then import httpx ===
exit: 0
ok -> httpx is now httpx2 2.13.1
این RuntimeError تنها جایی است که ارتقا خودش را لو میدهد. در بقیهی موارد، از جمله مسیر mock، هیچ خطایی نمیبینی و هیچ assertای نمیشکند.
راهنمای رسمی یک شرط دیگر هم دارد: کتابخانه هرگز نباید این تابع را بهجای کاربرش صدا بزند، و در برنامهها بهتر است فقط در نقطهی ورود باشد [1]. اگر توضیحنویسیهای نوعت httpx.Response را نام میبرند، همانها هم باید به httpx2 تغییر کنند [1].
سه چیزی که حذف شدهاند و هر کدام خطای خودش را دارند
بقیهی فهرست مهاجرت، حذف چیزهایی است که از قبل منسوخ اعلام شده بودند. هر کدام را جداگانه روی همین نسخهی نصبشده امتحان کردیم و پیام خطای واقعی را گرفتیم.
# سه چیزی که در 1.x حذف شدهاند؛ هر سه بدون کلید API بررسی میشوند
import anthropic
c = anthropic.Anthropic(api_key="x")
print("client.completions:", hasattr(c, "completions"))
try:
c.messages.create(model="claude-sonnet-4-5", max_tokens=16,
messages=[{"role": "user", "content": "hi"}],
temperature=0.0)
except TypeError as e:
print("TypeError:", e)
try:
c.beta.messages.parse(model="claude-sonnet-4-5", max_tokens=16,
messages=[{"role": "user", "content": "hi"}],
output_format={"type": "json_schema", "schema": {}})
except TypeError as e:
print("TypeError:", e)
try:
anthropic.AnthropicBedrock(api_key="x")
except ValueError as e:
print("ValueError:", str(e)[:90], "...")
$ python3 removals.py
client.completions: False
TypeError: Messages.create() got an unexpected keyword argument 'temperature'
TypeError: `output_format` must be a type; pass a schema dict as `output_config={'format': ...}` instead
ValueError: No AWS region was provided. Set the `aws_region` argument, the `AWS_REGION` / `AWS_DEFAULT ...
سه نکته از همین خروجی درمیآید. حذف Text Completions یعنی client.completions دیگر وجود ندارد و باید به client.messages.create() بروی [1][9]. حذف پارامترهای نمونهبرداری فقط از امضای متدها اتفاق افتاده، نه از خود API؛ اگر روی مدل قدیمی به آن نیاز داری، از extra_body رد کنی [1]. و خطای Bedrock دیگر آن هشدار خاموش به us-east-1 نیست [1].
اگر پروژهای که مهاجرت میکنی روی یک مدل تازه کار میکند، این سه خطا را جدی نگیر: کدی که فقط client.messages.create() با پارامترهای ساده صدا میزند بیسروصدا کار میکند.
ترتیب کار، و جایی که Claude Code کمک میکند
راهنمای رسمی خودش دستور کار را نوشته است: با pip install --upgrade "anthropic>=1,<2" شروع کن، بعد بررسی نوع را اجرا کن، بعد موارد را به ترتیب دستهبندی کن [1].
# گام یک: نصب را در یک خط قفل کن تا CI نتواند به 0.x برگردد
$ pip install --upgrade "anthropic>=1,<2"
# گام دو: چکلیست ماشینی. تقریبا همهی موارد فهرست زیر را خطا نشان میدهد
$ pyright
# گام سه: موارد باقیمانده را دستهبهدسته اصلاح کن
# ۱. import های httpx در کدی که به SDK چیزی میدهد
# ۲. alias_httpx در نقطهی ورود، اگر respx یا OTel داری
# ۳. await روی متدهای raw-response در مسیر async
# ۴. حذف temperature و top_p و top_k
# ۵. aws_region برای Bedrock
از نسخهی 2.1.239 کلاد کد، دستور /claude-api upgrade python همین کار را برای پروژههای پایتون انجام میدهد و راهنمای رسمی SDK هم پیشنهاد میکند از آن شروع کنید و diff را بازبینی کنید [1][3]. تاریخ انتشار این نسخه ۲۱ اوت ۲۰۲۶ است [3].
این فرمان در یک نشست غیرتعاملی، مثل CI، قابل اجرا نیست. تفاوتش این است که بهجای فهرست، diff میدهد؛ و diff را باید خواند.
اگر هنوز آمادهی مهاجرت نیستی، پین کردن به anthropic>=0.125,<1 خط را نگه میدارد. آخرین نسخهی خط 0.x همان 0.125.0 است [5]. اگر روی Bedrock هستی، ناحیه را قبل از ارتقا تعیین کن.
برای مقایسه، پست تست ایجنت Pydantic AI بدون کلید API همین اصل را در سمت دیگر نشان میدهد: وقتی مسیر را بدون کلید اجرا کنی، میتوانی یک مهاجرت را بدون هزینهی API هم بسنجی.
جمعبندی: چه چیزی را از این پست بردارید
سه قاعدهی عملی از این اجرا بیرون میآید. اول اینکه یک بررسی هویتی روی ماژول، بیشتر از یک تست بلند ارزش دارد: هم httpx قدیمی را لو میدهد و هم هر کلاینت دیگری را که در همان فرایند روی پشتهی قدیمی مانده است.
دوم اینکه تست سبز، در این مهاجرت، دلیل سلامت نیست. اگر با respx تست مینویسی، بعد از ارتقا یک تست اضافه کن که صریحا اثبات کند یک درخواست گرفته شده است.
سوم اینکه httpx2.alias_httpx() را مثل یک دستور import تلقی کن نه یک تابع کمکی: باید قبل از هر چیزی که httpx را import میکند اجرا شود، وگرنه با RuntimeError میایستد که تنها هشدار خودِ ارتقا است.
همهی اعداد این پست از همین اجراها روی همین ماشین آمدهاند: anthropic نسخهی 1.8.0 نصبشده، httpx2 نسخهی 2.13.1، و آخرین نسخهی موجود روی PyPI در لحظهی خواندن 1.12.1 با requires_python برابر >=3.10.
منابع
- راهنمای مهاجرت رسمی SDK پایتون Anthropic به نسخهی 1
- یادداشت انتشار نسخهی v1.0.0 در ۲۰ اوت ۲۰۲۶
- یادداشت انتشار کلاد کد 2.1.239 در ۲۱ اوت ۲۰۲۶
- ریپوی fork بهنام httpx2، نگهداریشده توسط تیم Pydantic
- صفحهی بستهی anthropic روی PyPI و فهرست نسخهها
- صفحهی بستهی httpx2 روی PyPI
- مستندات SDK پایتون در پلتفرم Claude
- مستندات خروجی ساختیافته و output_config
- راهنمای کار با Messages API
دیدگاهها
۰ موردهنوز دیدگاهی ثبت نشده. اولین نفر باشید.