GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||
GeezerVison is showing python.github.io — venv --- ایجاد محیطهای مجازی
|
سکو |
پوسته |
دستور فعالسازی محیط مجازی |
|---|---|---|
POSIX |
bash/zsh |
|
ماهی |
|
|
csh/tcsh |
|
|
pwsh |
|
|
ویندوز |
cmd.exe |
|
PowerShell |
|
اضافه شده در نسخهی 3.4: اسکریپتهای فعالسازی fish و csh.
اضافه شده در نسخهی 3.8: اسکریپتهای فعالسازی PowerShell نصبشده تحت POSIX برای پشتیبانی از PowerShell Core.
شما لزوماً نیاز ندارید یک محیط مجازی را فعال کنید، زیرا میتوانید صرفاً مسیر کامل مفسر پایتون آن محیط را هنگام فراخوانی پایتون مشخص کنید. علاوه بر این، تمام اسکریپتهای نصبشده در محیط باید بدون فعالسازی آن قابل اجرا باشند.
برای دستیابی به این هدف، اسکریپتهای نصبشده در محیطهای مجازی دارای یک خط «shebang» هستند که به مفسر پایتون محیط اشاره میکند، #!/<path-to-venv>/bin/python. این بدان معناست که اسکریپت صرفنظر از مقدار PATH با آن مفسر اجرا میشود. در ویندوز، پردازش خط «shebang» در صورتی پشتیبانی میشود که مدیر نصب پایتون را نصب کرده باشید. بنابراین، دوبار کلیک روی یک اسکریپت نصبشده در یک پنجرهی Windows Explorer باید آن را با مفسر صحیح اجرا کند، بدون نیاز به فعالسازی محیط یا قرار داشتن آن در PATH.
هنگامی که یک محیط مجازی فعال شده باشد، متغیر محیطی VIRTUAL_ENV روی مسیر آن محیط تنظیم میشود. از آنجا که برای استفاده از یک محیط مجازی نیازی به فعالسازی صریح آن نیست، نمیتوان برای تعیین اینکه آیا یک محیط مجازی در حال استفاده است، به VIRTUAL_ENV اتکا کرد.
هشدار
از آنجا که اسکریپتهای نصبشده در محیطها نباید انتظار داشته باشند که محیط فعال شده باشد، سطرهای shebang آنها حاوی مسیرهای مطلق به مفسرهای محیط خود هستند. به همین دلیل، محیطها در حالت کلی ذاتاً غیرقابلانتقال هستند. شما همیشه باید راهی ساده برای بازسازی یک محیط داشته باشید (برای مثال، اگر یک پرونده نیازمندیها با نام requirements.txt دارید، میتوانید با استفاده از pip همان محیط، دستور pip install -r requirements.txt را اجرا کنید تا تمام بستههای موردنیاز محیط نصب شوند). اگر به هر دلیلی نیاز دارید محیط را به مکان جدیدی منتقل کنید، باید آن را در مکان دلخواه بازسازی کنید و محیط موجود در مکان قدیمی را حذف کنید. اگر محیطی را به این دلیل جابهجا میکنید که پوشه والد آن را جابهجا کردهاید، باید محیط را در مکان جدید آن بازسازی کنید. در غیر این صورت، ممکن است نرمافزار نصبشده در محیط آنطور که انتظار میرود کار نکند.
شما میتوانید با تایپ deactivate در پوسته، یک محیط مجازی را غیرفعال کنید. سازوکار دقیق آن به سکو بستگی دارد و جزئیاتی از پیادهسازی داخلی است (معمولاً از یک اسکریپت یا تابع پوسته استفاده میشود).
متد سطح بالایی که در بالا توضیح داده شد، از یک API ساده استفاده میکند که سازوکارهایی را برای سازندگان محیطهای مجازی شخص ثالث فراهم میکند تا ایجاد محیط را مطابق نیازهای خود سفارشیسازی کنند: کلاس EnvBuilder.
کلاس EnvBuilder در هنگام نمونهسازی، آرگومانهای کلیدواژهای زیر را میپذیرد:
system_site_packages -- یک مقدار بولی که نشان میدهد site-packages پایتون سیستم باید برای محیط در دسترس باشد (پیشفرض False است).
clear -- یک مقدار بولی که اگر درست باشد، محتوای هر پوشه هدف موجود را پیش از ایجاد محیط حذف میکند.
symlinks -- یک مقدار بولی که نشان میدهد آیا باید بهجای کپی کردن، برای ایجاد پیوند نمادیندودویی Python تلاش شود یا خیر.
upgrade -- یک مقدار بولی که اگر true باشد، محیط موجود را با پایتون در حال اجرا ارتقا میدهد - برای استفاده زمانی که آن پایتون بهصورت درجا (in-place) ارتقا یافته است (پیشفرض False).
with_pip -- یک مقدار بولی که اگر true باشد، تضمین میکند pip در محیط مجازی نصب شده باشد. این کار از ensurepip با گزینهی --default-pip استفاده میکند.
prompt -- رشتهای که پس از فعالسازی محیط مجازی استفاده میشود (پیشفرض آن None است، یعنی از نام پوشهی محیط استفاده میشود). اگر رشتهی خاص "." ارائه شود، نام پایه (basename) پوشهی جاری بهعنوان prompt استفاده میشود.
upgrade_deps -- بهروزرسانی ماژولهای پایه venv به آخرین نسخههای موجود در PyPI
scm_ignore_files -- برای مدیران کنترل منبع (SCM) مشخصشده در پیمایشپذیر، پروندههای نادیدهگرفتن (ignore files) ایجاد میکند. پشتیبانی با داشتن متدی به نام create_{scm}_ignore_file تعریف میشود. تنها مقدار پشتیبانیشده بهصورت پیشفرض "git" از طریق create_git_ignore_file() است.
تغییر یافته در نسخهی 3.4: پارامتر with_pip افزوده شد
تغییر یافته در نسخهی 3.6: پارامتر prompt اضافه شد
تغییر یافته در نسخهی 3.9: پارامتر upgrade_deps اضافه شد
تغییر یافته در نسخهی 3.13: پارامتر scm_ignore_files افزوده شد
میتوان از EnvBuilder بهعنوان کلاس پایه استفاده کرد.
با مشخص کردن پوشه هدف (بهصورت مطلق یا نسبی به پوشه فعلی) که باید حاوی محیط مجازی باشد، یک محیط مجازی ایجاد کنید. متد create یا محیط را در پوشه مشخصشده ایجاد میکند، یا استثنای مناسبی را پرتاب میکند.
متد create کلاس EnvBuilder قلابهای در دسترس (hooks) برای سفارشیسازی در زیرکلاسها را نشان میدهد:
def create(self, env_dir): """ یک محیط پایتون مجازیسازیشده را در یک پوشه ایجاد میکند. env_dir پوشه هدف برای ایجاد یک محیط است. """ env_dir = os.path.abspath(env_dir) context = self.ensure_directories(env_dir) self.create_configuration(context) self.setup_python(context) self.setup_scripts(context) self.post_setup(context)
هر یک از متدهای ensure_directories()، create_configuration()، setup_python()، setup_scripts() و post_setup() را میتوان بازنویسی کرد.
پوشهی محیط و تمام زیرپوشههای ضروری را که از قبل وجود ندارند، ایجاد میکند و یک شیء زمینه را برمیگرداند. این شیء زمینه فقط نگهدارندهای برای ویژگیها (مانند مسیرها) برای استفاده توسط سایر متدها است. اگر EnvBuilder با آرگومان clear=True ایجاد شود، محتویات پوشهی محیط پاک خواهد شد و سپس تمام زیرپوشههای ضروری دوباره ایجاد خواهند شد.
شیء زمینهی برگرداندهشده یک types.SimpleNamespace با ویژگیهای زیر است:
env_dir - محل محیط مجازی. برای __VENV_DIR__ در اسکریپتهای فعالسازی به کار میرود (به install_scripts() مراجعه کنید).
env_name - نام محیط مجازی. برای __VENV_NAME__ در اسکریپتهای فعالسازی استفاده میشود (به install_scripts() مراجعه کنید).
prompt - اعلانی که توسط اسکریپتهای فعالسازی استفاده میشود. برای __VENV_PROMPT__ در اسکریپتهای فعالسازی استفاده میشود (به install_scripts() مراجعه کنید).
executable - پرونده اجرایی پایتونِ زیربنایی که محیط مجازی از آن استفاده میکند. این، حالتی را در نظر میگیرد که در آن یک محیط مجازی از یک محیط مجازی دیگر ایجاد شده باشد.
inc_path - مسیر include (include path) برای محیط مجازی.
lib_path - مسیر purelib برای محیط مجازی.
platlib_path - مسیر platlib برای محیط مجازی.
bin_path - مسیر اسکریپت برای محیط مجازی.
bin_name - نام مسیر اسکریپت نسبت به محل محیط مجازی. برای __VENV_BIN_NAME__ در اسکریپتهای فعالسازی استفاده میشود (به install_scripts() مراجعه کنید).
env_exe - نام مفسر پایتون در محیط مجازی. برای __VENV_PYTHON__ در اسکریپتهای فعالسازی استفاده میشود (به install_scripts() مراجعه کنید).
env_exec_cmd - نام مفسر پایتون، با در نظر گرفتن تغییر مسیرهای سامانه فایلبندی. میتوان از آن برای اجرای پایتون در محیط مجازی استفاده کرد.
تغییر یافته در نسخهی 3.11: از طرحواره نصب sysconfig مربوط به venv برای ساخت مسیرهای پوشههای ایجادشده استفاده میشود.
تغییر یافته در نسخهی 3.12: ویژگی lib_path به زمینه افزوده شد و شیء زمینه مستند شد.
تغییر یافته در نسخهی 3.15: ویژگی platlib_path به زمینه اضافه شد.
پرونده پیکربندی pyvenv.cfg را در محیط ایجاد میکند.
یک رونوشت یا پیوند نمادین به پرونده اجرایی پایتون را در محیط ایجاد میکند. در سیستمهای POSIX، اگر از یک پرونده اجرایی مشخص python3.x استفاده شده باشد، پیوندهای نمادین python و python3 ایجاد میشوند که به آن پرونده اجرایی اشاره میکنند، مگر اینکه پروندههایی با آن نامها از قبل وجود داشته باشند.
اسکریپتهای فعالسازی متناسب با پلتفرم را در محیط مجازی نصب میکند.
بستههای وابستگی اصلی venv (در حال حاضر pip) را در محیط ارتقا میدهد. این کار با فراخوانی پرونده اجرایی pip در محیط از طریق پوسته انجام میشود.
اضافه شده در نسخهی 3.9.
تغییر یافته در نسخهی 3.12: setuptools دیگر یک وابستگی اصلی برای venv نیست.
یک متد جاینگهدار که میتوان آن را در پیادهسازیهای شخص ثالث بازنویسی کرد تا بستهها را از پیش در محیط مجازی نصب کند یا سایر مراحل پس از ایجاد را انجام دهد.
این متد را میتوان از setup_scripts() یا post_setup() در زیرکلاسها فراخوانی کرد تا به نصب اسکریپتهای سفارشی در محیط مجازی کمک کند.
path مسیر پوشهای است که باید شامل زیرپوشههای common، posix و nt باشد؛ هر یک حاوی اسکریپتهایی که برای پوشهی bin در محیط در نظر گرفته شدهاند. محتویات common و پوشهی متناظر با os.name پس از انجام برخی جایگزینیهای متنی برای جاینگهدارها کپی میشوند:
__VENV_DIR__ با مسیر مطلق پوشهی محیط جایگزین میشود.
__VENV_NAME__ با نام محیط جایگزین میشود (آخرین بخش مسیر پوشهی محیط).
__VENV_PROMPT__ با اعلان (prompt) جایگزین میشود (نام محیط داخل پرانتز بههمراه یک فاصله پس از آن)
__VENV_BIN_NAME__ با نام پوشهی bin (یا bin یا Scripts) جایگزین میشود.
__VENV_PYTHON__ با مسیر مطلق پرونده اجرایی محیط جایگزین میشود.
وجود پوشهها مجاز است (برای زمانی که یک محیط موجود در حال ارتقا است).
یک پرونده .gitignore درون محیط مجازی ایجاد میکند که باعث میشود کل پوشه توسط مدیر کنترل منبع Git نادیده گرفته شود.
اضافه شده در نسخهی 3.13.
تغییر یافته در نسخهی 3.7.2: ویندوز اکنون بهجای کپی کردن دودوییهای واقعی، برای python[w].exe از اسکریپتهای تغییرمسیردهنده استفاده میکند. فقط در 3.7.2، setup_python() هیچ کاری انجام نمیدهد، مگر اینکه از یک ساخت در درخت منبع (source tree) اجرا شود.
تغییر یافته در نسخهی 3.7.3: ویندوز اسکریپتهای تغییرمسیردهنده (redirector) را بهعنوان بخشی از setup_python() کپی میکند، نه بهعنوان بخشی از setup_scripts(). این موضوع در 3.7.2 اینگونه نبود. هنگام استفاده از پیوندهای نمادین، پروندههای اجرایی اصلی پیوند داده خواهند شد.
همچنین یک تابع کمکی در سطح ماژول وجود دارد:
یک EnvBuilder با آرگومانهای کلیدواژهای دادهشده ایجاد کنید و متد create() آن را با آرگومان env_dir فراخوانی کنید.
اضافه شده در نسخهی 3.3.
تغییر یافته در نسخهی 3.4: پارامتر with_pip اضافه شد
تغییر یافته در نسخهی 3.6: پارامتر prompt اضافه شد
تغییر یافته در نسخهی 3.9: پارامتر upgrade_deps افزوده شد
تغییر یافته در نسخهی 3.13: پارامتر scm_ignore_files افزوده شد
EnvBuilder¶اسکریپت زیر نشان میدهد که چگونه میتوان EnvBuilder را با پیادهسازی زیرکلاسی که setuptools و pip را در یک محیط مجازی ایجادشده نصب میکند، گسترش داد:
import os import os.path from subprocess import Popen, PIPE import sys from threading import Thread from urllib.parse import urlsplit from urllib.request import urlretrieve import venv class ExtendedEnvBuilder(venv.EnvBuilder): """ This builder installs setuptools and pip so that you can pip or easy_install other packages into the created virtual environment. :param nodist: If true, setuptools and pip are not installed into the created virtual environment. :param nopip: If true, pip is not installed into the created virtual environment. :param progress: If setuptools or pip are installed, the progress of the installation can be monitored by passing a progress callable. If specified, it is called with two arguments: a string indicating some progress, and a context indicating where the string is coming from. The context argument can have one of three values: 'main', indicating that it is called from virtualize() itself, and 'stdout' and 'stderr', which are obtained by reading lines from the output streams of a subprocess which is used to install the app. If a callable is not specified, default progress information is output to sys.stderr. """ def __init__(self, *args, **kwargs): self.nodist = kwargs.pop('nodist', False) self.nopip = kwargs.pop('nopip', False) self.progress = kwargs.pop('progress', None) self.verbose = kwargs.pop('verbose', False) super().__init__(*args, **kwargs) def post_setup(self, context): """ Set up any packages which need to be pre-installed into the virtual environment being created. :param context: The information for the virtual environment creation request being processed. """ os.environ['VIRTUAL_ENV'] = context.env_dir if not self.nodist: self.install_setuptools(context) # Can't install pip without setuptools if not self.nopip and not self.nodist: self.install_pip(context) def reader(self, stream, context): """ Read lines from a subprocess' output stream and either pass to a progress callable (if specified) or write progress information to sys.stderr. """ progress = self.progress while True: s = stream.readline() if not s: break if progress is not None: progress(s, context) else: if not self.verbose: sys.stderr.write('.') else: sys.stderr.write(s.decode('utf-8')) sys.stderr.flush() stream.close() def install_script(self, context, name, url): _, _, path, _, _ = urlsplit(url) fn = os.path.split(path)[-1] binpath = context.bin_path distpath = os.path.join(binpath, fn) # Download script into the virtual environment's binaries folder urlretrieve(url, distpath) progress = self.progress if self.verbose: term = '\n' else: term = '' if progress is not None: progress('Installing %s ...%s' % (name, term), 'main') else: sys.stderr.write('Installing %s ...%s' % (name, term)) sys.stderr.flush() # Install in the virtual environment args = [context.env_exe, fn] p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath) t1 = Thread(target=self.reader, args=(p.stdout, 'stdout')) t1.start() t2 = Thread(target=self.reader, args=(p.stderr, 'stderr')) t2.start() p.wait() t1.join() t2.join() if progress is not None: progress('done.', 'main') else: sys.stderr.write('done.\n') # Clean up - no longer needed os.unlink(distpath) def install_setuptools(self, context): """ Install setuptools in the virtual environment. :param context: The information for the virtual environment creation request being processed. """ url = "https://bootstrap.pypa.io/ez_setup.py" self.install_script(context, 'setuptools', url) # clear up the setuptools archive which gets downloaded pred = lambda o: o.startswith('setuptools-') and o.endswith('.tar.gz') files = filter(pred, os.listdir(context.bin_path)) for f in files: f = os.path.join(context.bin_path, f) os.unlink(f) def install_pip(self, context): """ Install pip in the virtual environment. :param context: The information for the virtual environment creation request being processed. """ url = 'https://bootstrap.pypa.io/get-pip.py' self.install_script(context, 'pip', url) def main(args=None): import argparse parser = argparse.ArgumentParser(prog=__name__, description='Creates virtual Python ' 'environments in one or ' 'more target ' 'directories.') parser.add_argument('dirs', metavar='ENV_DIR', nargs='+', help='A directory in which to create the ' 'virtual environment.') parser.add_argument('--no-setuptools', default=False, action='store_true', dest='nodist', help="Don't install setuptools or pip in the " "virtual environment.") parser.add_argument('--no-pip', default=False, action='store_true', dest='nopip', help="Don't install pip in the virtual " "environment.") parser.add_argument('--system-site-packages', default=False, action='store_true', dest='system_site', help='Give the virtual environment access to the ' 'system site-packages dir.') if os.name == 'nt': use_symlinks = False else: use_symlinks = True parser.add_argument('--symlinks', default=use_symlinks, action='store_true', dest='symlinks', help='Try to use symlinks rather than copies, ' 'when symlinks are not the default for ' 'the platform.') parser.add_argument('--clear', default=False, action='store_true', dest='clear', help='Delete the contents of the ' 'virtual environment ' 'directory if it already ' 'exists, before virtual ' 'environment creation.') parser.add_argument('--upgrade', default=False, action='store_true', dest='upgrade', help='Upgrade the virtual ' 'environment directory to ' 'use this version of ' 'Python, assuming Python ' 'has been upgraded ' 'in-place.') parser.add_argument('--verbose', default=False, action='store_true', dest='verbose', help='Display the output ' 'from the scripts which ' 'install setuptools and pip.') options = parser.parse_args(args) if options.upgrade and options.clear: raise ValueError('you cannot supply --upgrade and --clear together.') builder = ExtendedEnvBuilder(system_site_packages=options.system_site, clear=options.clear, symlinks=options.symlinks, upgrade=options.upgrade, nodist=options.nodist, nopip=options.nopip, verbose=options.verbose) for d in options.dirs: builder.create(d) if __name__ == '__main__': rc = 1 try: main() rc = 0 except Exception as e: print('Error: %s' % e, file=sys.stderr) sys.exit(rc)
این اسکریپت همچنین بهصورت آنلاین برای بارگذاری در دسترس است.