Faragiri
فارسی

زبان را انتخاب کنید ۴

همهٔ زبان‌ها

آموزش بسته و محیط مجازی پایتون

محیط مجازی یک پوشه است و یک عدد که عوض می‌شود. تشخیصش یک سطر کد است و بدون آن، هر نصبی روی همه پروژه‌های ماشین اثر می‌گذارد.

۴بخش
۳دقیقه خواندن
۴عمق

چهار لایه، یک ایمپورت

وقتی import می‌نویسید، پایتون از کدام لایه‌ها می‌گذرد

هر لایه روی لایه زیر خودش ایستاده، و محیط مجازی فقط یکی از آن‌ها را عوض می‌کند.

  1. کد خود پروژهماژول‌های کنار فایل شما، که اول از همه پیدا می‌شوندلایه ۱
  2. بسته‌های محیط مجازیهمان پوشه‌ای که ساختید، و تنها لایه‌ای که پروژه‌ها از هم جدایشان می‌کندلایه ۲
  3. کتابخانه استانداردهمراه مفسر می‌آید و در هر محیطی یکی استلایه ۳
  4. مفسر سیستمهمان که base_prefix به آن اشاره می‌کند و نباید دستکاری شودلایه ۴

این لایه‌ها ترتیب جست‌وجو را می‌گویند و نه ترتیب نصب. یک بسته با نام تکراری در لایه بالاتر، همان نام را در لایه‌های پایین‌تر پنهان می‌کند و هیچ هشداری هم نمی‌دهد.

محیط مجازی چیز پیچیده‌ای نیست: یک پوشه که مفسر و بسته‌های یک پروژه در آن می‌نشینند. ساختنش یک دستور است، python3 -m venv .venv، و بعد از فعال کردن، یک سطر می‌گوید که واقعا داخلش هستید یا نه:

  • sys.prefix به همان پوشه .venv اشاره می‌کند
  • sys.base_prefix به مفسر اصلی سیستم اشاره می‌کند
  • وقتی این دو با هم فرق دارند، در محیط مجازی هستید

محیط تازه فقط pip دارد و هیچ چیز دیگری؛ فهرست بسته‌هایش یک سطر است. برای همین اولین import از یک بسته نصب‌نشده با ModuleNotFoundError: No module named 'requests' می‌ایستد، حتی اگر همان بسته روی مفسر سیستم نصب باشد. این جدا بودن، خود ویژگی است.

فایل قفل، و تفاوتش با فهرست وابستگی

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

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

نصب از ایران، و پرچمی که مقصد را عوض می‌کند

درخواست pip install به pypi.org می‌رود و همان درخواست است که معمولا به نتیجه نمی‌رسد. دو پرچم این را حل می‌کنند: --index-url که مقصد را به یک آینه عوض می‌کند و --trusted-host که میزبان آینه را قابل اعتماد اعلام می‌کند. نوشتن آن‌ها در هر دستور خسته‌کننده است، پس یک بار در فایل pip.conf ثبتشان کنید و از آن به بعد همه دستورها از همان مسیر می‌روند.

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

جایی که کار گیر می‌کند، نصب سراسری است

رایج‌ترین اتفاق این است که یک تازه‌کار همه چیز را با pip install بدون محیط مجازی نصب می‌کند و ماه‌ها هیچ مشکلی هم پیش نمی‌آید. مسئله وقتی شروع می‌شود که پروژه دوم بیاید و نسخه دیگری از همان کتابخانه بخواهد: نصب دومی، اولی را می‌شکند، و هیچ خطایی هم درباره این موضوع داده نمی‌شود؛ فقط پروژه قبلی از یک روز به بعد کار نمی‌کند. روی مک و لینوکس این حتی بدتر است، چون بعضی ابزارهای خود سیستم‌عامل به همان مفسر وابسته‌اند. عادت درست ساده است: هر پوشه پروژه، یک .venv خودش.

ابزار، و سالی که این حرف درست است

در سال ۲۰۲۶ ماژول venv در کتابخانه استاندارد و رایگان است و جای بسته بیرونی virtualenv را گرفته که پیش از پایتون 3.3 تنها راه بود. pip از حدود سال ۲۰۱۱ جانشین easy_install شد و همراه خود پایتون می‌آید. ابزار تازه‌تری که هم محیط را می‌سازد و هم نصب را انجام می‌دهد و به‌مراتب سریع‌تر است uv است؛ متن‌باز است و فایل قفل را خودش می‌نویسد، اما خودش هم باید یک بار نصب شود.

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

کنار این

بالای این