ایران‌ویا
مقالات آموزشی

میرور PyPI ایرانی: تنظیم pip، Poetry و uv

۸ دقیقه
میرور PyPI ایرانی: تنظیم pip، Poetry و uv

برای رفع خطای pip install در ایران کافی است آدرس ایندکس پیش‌فرض pip را به میرور (mirror) داخلی تغییر دهید: pip config set global.index-url https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/. از این لحظه همه‌ی پکیج‌های پایتون از زیرساخت داخلی نوین کلاد (Novin Cloud) تحویل می‌شوند؛ بدون تحریم، بدون تحریم‌شکن و با سرعت شبکه‌ی داخل کشور. در ادامه همین کار را برای Poetry، uv، Pipenv، Conda، داکر و خطوط CI/CD انجام می‌دهیم.

چرا pip install در ایران شکست می‌خورد؟

مخزن رسمی پکیج‌های پایتون یعنی PyPI و شبکه‌ی توزیع فایل آن، درخواست‌های خروجی از ایران را محدود می‌کنند. نتیجه‌اش سه الگوی خطای آشناست که هر توسعه‌دهنده‌ی پایتون دیده است: قطع شدن اتصال وسط دانلود، مهلت زمانی (timeout) طولانی و در نهایت پیام Could not fetch URL ... There was a problem confirming the ssl certificate.

راه‌حل‌های رایج هم هرکدام هزینه‌ی خودشان را دارند. تحریم‌شکن روی سرور تولیدی (production) هم ناپایدار است و هم از نظر امنیتی توجیه‌پذیر نیست. دانلود دستی فایل‌های wheel و انتقالشان به سرور، وابستگی‌های تودرتو را حل نمی‌کند. استفاده از پراکسی عمومی هم یعنی سپردن ترافیک بیلد به سرویسی که کنترلی رویش ندارید.

میرور داخلی دقیقاً همین گلوگاه را حذف می‌کند: یک نسخه‌ی آینه از مخزن (repository) اصلی که داخل ایران میزبانی می‌شود و با تغییر یک آدرس، جایگزین مخزن خارجی می‌شود. همین الگو را پیش‌تر برای جاوااسکریپت در رفع خطای npm install با میرور نوین کلاد و برای کانتینرها در میرور داکر هاب بررسی کردیم.

میرور PyPI نوین کلاد چه چیزی سرو می‌کند؟

سرویس میرورها و مخزن‌های نوین کلاد روی دامنه‌ی mirror.novin.cloud بیش از ۷۹ مخزن عمومی را آینه کرده است؛ از توزیع‌های لینوکس و پکیج‌منیجرهای زبان‌های مختلف تا ایمیج‌های داکر و چارت‌های Helm. این سرویس عمومی و رایگان است و برای دریافت پکیج به حساب کاربری، کلید API یا لاگین نیاز ندارید.

برای اکوسیستم پایتون سه نقطه‌ی پایانی (endpoint) اهمیت دارد:

کاربردآدرس
ایندکس PyPI برای pip و Poetry و uvhttps://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/
کانال اصلی Condahttps://mirror.novin.cloud/artifactory/api/conda/conda/main
کانال conda-forgehttps://mirror.novin.cloud/artifactory/api/conda/conda-forge
سورس تاربال‌های CPythonhttps://mirror.novin.cloud/python-source/

زیرساخت میرور روی JFrog Artifactory اجرا می‌شود و مخزن‌هایی که استفاده می‌کنید از نوع virtual هستند: یک آدرس واحد که پشت صحنه هم کش محلی و هم مخزن بالادستی را پوشش می‌دهد. به همین دلیل لازم نیست دنبال نام‌هایی مثل -local یا -remote بگردید. فهرست کامل مخزن‌ها در مستندات همه‌ی مخزن‌ها آمده است.

تنظیم pip؛ چهار روش از موقتی تا دائمی

۱. دستور pip config (روش توصیه‌شده)

ساده‌ترین و پایدارترین راه، نوشتن تنظیم در فایل پیکربندی کاربر با خود pip است:

pip config set global.index-url https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/

این دستور فایل تنظیمات را در مسیر درست سیستم‌عامل شما می‌سازد یا به‌روزرسانی می‌کند و نیازی به ویرایش دستی ندارد.

۲. ویرایش مستقیم فایل pip.conf

اگر می‌خواهید تنظیم را داخل ایمیج، اسکریپت نصب یا فایل پیکربندی نسخه‌بندی‌شده قرار دهید، فایل را مستقیم بنویسید. ساختار فایل از نوع INI است:

[global]
index-url = https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/

مسیر این فایل بر اساس سیستم‌عامل و دامنه‌ی اثر متفاوت است:

سطحلینوکس / مکویندوز
کاربر~/.config/pip/pip.conf (یا ~/.pip/pip.conf)%APPDATA%\pip\pip.ini
سراسری/etc/pip.confC:\ProgramData\pip\pip.ini
محیط مجازی$VIRTUAL_ENV/pip.conf%VIRTUAL_ENV%\pip.ini

ترتیب اولویت در pip از بالا به پایین این‌گونه است: گزینه‌های خط فرمان، سپس متغیرهای محیطی و در آخر فایل‌های پیکربندی. جزئیات کامل در مستندات رسمی pip آمده است.

۳. متغیر محیطی PIP_INDEX_URL

برای داکر، CI و هر جایی که نمی‌خواهید فایل اضافه بسازید، متغیر محیطی بهترین انتخاب است. هر گزینه‌ی بلند pip معادل یک متغیر با پیشوند PIP_ دارد:

export PIP_INDEX_URL=https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/
pip install -r requirements.txt

۴. نصب تکی بدون تغییر تنظیمات

اگر فقط برای یک نصب به میرور نیاز دارید، سوییچ -i کافی است و چیزی در سیستم شما تغییر نمی‌کند:

pip install requests -i https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/

بررسی این‌که تنظیمات واقعاً اعمال شده است

دو دستور زیر تنظیم فعلی و مسیر واقعی دانلود را نشان می‌دهند:

pip config list
pip download requests -d /tmp --no-deps -v | grep mirror

اگر خروجی دستور دوم شامل mirror.novin.cloud بود، پیکربندی درست انجام شده است. برای بازگشت به حالت قبل هم کافی است تنظیم را حذف کنید:

pip config unset global.index-url

پیکربندی Poetry با میرور داخلی

Poetry منبع پکیج را در فایل pyproject.toml پروژه نگه می‌دارد، نه در تنظیمات سراسری کاربر. یعنی پیکربندی میرور همراه مخزن کد شما جابه‌جا می‌شود و همه‌ی اعضای تیم و سرور CI به‌طور خودکار از همان آدرس استفاده می‌کنند:

poetry source add --priority=primary novin-mirror https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/

خروجی این دستور بلوک زیر است که می‌توانید مستقیم هم بنویسید:

[[tool.poetry.source]]
name = "novin-mirror"
url = "https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/"
priority = "primary"

نکته‌ی کلیدی در انتخاب priority است. Poetry سه سطح دارد:

  1. primary — همه‌ی منابع primary برای هر وابستگی جست‌وجو می‌شوند و به‌محض تعریف حداقل یک منبع primary، منبع ضمنی PyPI غیرفعال می‌شود. این همان چیزی است که برای عبور از تحریم می‌خواهیم.
  2. supplemental — فقط وقتی جست‌وجو می‌شود که منابع با اولویت بالاتر نتیجه‌ای ندهند.
  3. explicit — تنها زمانی استفاده می‌شود که یک پکیج صریحاً به آن منبع ارجاع داده شده باشد.

بعد از افزودن منبع، فایل قفل را دوباره بسازید تا آدرس‌های ذخیره‌شده در آن به‌روز شوند:

poetry lock
poetry install

توضیح کامل سطوح اولویت در مستندات رسمی Poetry آمده است.

uv، Pipenv و Conda

uv

uv هم از متغیر محیطی پشتیبانی می‌کند و هم از پیکربندی داخل پروژه. متغیر توصیه‌شده‌ی امروز UV_DEFAULT_INDEX است؛ متغیر قدیمی‌تر UV_INDEX_URL هنوز کار می‌کند اما در مستندات رسمی به‌عنوان منسوخ (deprecated) علامت خورده است:

export UV_DEFAULT_INDEX=novin=https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/
uv sync

برای تثبیت تنظیم در خود پروژه، این بلوک را به pyproject.toml اضافه کنید:

[[tool.uv.index]]
name = "novin"
url = "https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/"
default = true

مقدار default = true این ایندکس را جایگزین PyPI می‌کند.

Pipenv

در Pipenv منبع داخل فایل Pipfile تعریف می‌شود:

[[source]]
url = "https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/"
verify_ssl = true
name = "novin-mirror"

Conda

اگر با Conda کار می‌کنید، کانال‌ها را در فایل ~/.condarc بنویسید:

channels:
  - https://mirror.novin.cloud/artifactory/api/conda/conda/main
default_channels:
  - https://mirror.novin.cloud/artifactory/api/conda/conda/main

و برای بررسی: conda config --show channels و سپس conda install numpy --dry-run -v. راهنمای کامل هر سه ابزار در مستندات pip نوین کلاد و صفحه‌ی Conda موجود است.

اگر خود مفسر پایتون را از سورس می‌سازید یا از pyenv استفاده می‌کنید، دانلود تاربال‌ها هم می‌تواند از میرور انجام شود:

export PYTHON_BUILD_MIRROR_URL=https://mirror.novin.cloud/python-source
pyenv install 3.12.6

داکر و CI/CD؛ جایی که میرور بیشترین سود را دارد

روی لپ‌تاپ، شکست نصب یک پکیج آزاردهنده است؛ روی خط CI/CD همان شکست یعنی بیلد قرمز و استقرار عقب‌افتاده. چون هر بیلد از صفر پکیج‌ها را دانلود می‌کند، وابستگی به سرور خارجی در این نقطه بیشترین آسیب را می‌زند.

در Dockerfile فقط یک خط لازم است:

FROM python:3.12-slim
ENV PIP_INDEX_URL=https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

در GitLab CI یا GitHub Actions همان متغیر را در بخش متغیرهای محیطی جاب تعریف کنید تا همه‌ی مراحل از میرور استفاده کنند:

variables:
  PIP_INDEX_URL: "https://mirror.novin.cloud/artifactory/api/pypi/pypi/simple/"

اگر ایمیج پایه‌ی خود پایتون هم کند یا غیرقابل‌دریافت است، ترکیب این تنظیم با رجیستری داکر نوین کلاد کل چرخه‌ی بیلد را داخلی می‌کند. برای تیم‌هایی که بیلدها را روی کوبرنتیز مدیریت‌شده اجرا می‌کنند، تعریف این متغیر در ConfigMap مشترک، پیکربندی را یک‌جا و برای همه‌ی Podها اعمال می‌کند. برای اجرای ساده‌تر روی یک ماشین، سرور مجازی نوین کلاد در کنار میرور، محیط توسعه‌ی بدون تحریمی می‌سازد. استارتاپ‌هایی که تازه زیرساختشان را می‌چینند می‌توانند از راهکار استارتاپ‌ها شروع کنند.

عیب‌یابی خطاهای رایج

نشانهعلت محتملراه‌حل
هنوز ترافیک به سمت pypi.org می‌رودتنظیم در سطح دیگری بازنویسی شده استpip config list بگیرید؛ به یاد داشته باشید خط فرمان بر متغیر محیطی و آن بر فایل تنظیمات اولویت دارد
خطای گواهی SSLپراکسی یا تحریم‌شکن هنوز فعال استمتغیرهای http_proxy و https_proxy را خالی کنید؛ میرور داخلی به پراکسی نیاز ندارد
یک پکیج پیدا نمی‌شودورژن خیلی تازه هنوز کش نشده استچند دقیقه بعد دوباره تلاش کنید؛ مخزن virtual پس از اولین درخواست از بالادست می‌گیرد
خطای ۵۰۲اختلال موقتی سمت سرویسدرخواست را تکرار کنید و در صورت ادامه تیکت پشتیبانی ثبت کنید
نصب در داکر کار نمی‌کند ولی روی سیستم درست استفایل pip.conf کاربر داخل ایمیج وجود ندارداز ENV PIP_INDEX_URL استفاده کنید نه فایل تنظیمات میزبان

نکته‌ی مهم درباره‌ی فایل‌های قفل: اگر poetry.lock یا uv.lock پیش‌تر با آدرس PyPI ساخته شده باشد، آدرس منبع داخل فایل ذخیره شده است. بعد از تغییر منبع، فایل قفل را دوباره بسازید تا نصب واقعاً از میرور انجام شود.

سؤالات متداول

آیا استفاده از میرور PyPI نوین کلاد رایگان است؟

بله. سرویس میرور عمومی و رایگان است و برای دریافت پکیج به حساب کاربری، کلید API یا لاگین نیاز ندارید.

آیا همه‌ی پکیج‌های PyPI روی میرور موجودند؟

مخزن از نوع virtual است؛ یعنی هر درخواست را در صورت نبود در کش، از مخزن بالادستی می‌گیرد و ذخیره می‌کند. بنابراین دامنه‌ی پکیج‌ها همان PyPI است، فقط مسیر دریافت داخلی می‌شود.

آیا پکیج خصوصی شرکتم را هم می‌توانم روی این آدرس منتشر کنم؟

خیر. این آدرس فقط برای خواندن و دریافت پکیج‌های عمومی است. برای انتشار پکیج خصوصی به مخزن اختصاصی خودتان نیاز دارید.

اگر بخواهم به تنظیمات قبلی برگردم چه کنم؟

با pip config unset global.index-url تنظیم حذف می‌شود و pip دوباره سراغ PyPI می‌رود. در Poetry بلوک منبع را از pyproject.toml بردارید و در Conda کانال را با conda config --remove channels حذف کنید.

آیا برای استفاده از میرور باید سرورم در ایران باشد؟

خیر، اما بیشترین سود سرعت وقتی به دست می‌آید که سرور یا سیستم شما داخل ایران باشد، چون ترافیک از مسیر داخلی سرو می‌شود.

جمع‌بندی

تنظیم میرور PyPI یک تغییر تک‌خطی است که سه دستاورد دارد: حذف وابستگی به تحریم‌شکن، سرعت داخلی در دانلود و مهم‌تر از همه، بیلدهای CI/CD قابل‌اتکا. برای pip یک دستور pip config set، برای Poetry یک بلوک [[tool.poetry.source]] با اولویت primary و برای داکر یک خط ENV کافی است.

اگر بقیه‌ی زنجیره‌ی توسعه‌تان هم درگیر تحریم است، همین رویکرد برای npm، داکر، Maven و مخزن‌های لینوکس هم کار می‌کند. فهرست کامل در صفحه‌ی میرورهای نوین کلاد و معرفی میرورها در مستندات آمده است. سرویس میرور نوین کلاد (Novin Cloud) — که گاهی با نام‌های ابرنوین یا نوین کلود هم شناخته می‌شود — بدون ثبت‌نام در دسترس شماست؛ کافی است آدرس ایندکس را عوض کنید و اولین pip install بدون خطا را ببینید.