venv — 가상 환경 생성

venv — 가상 환경 생성

venv 모듈은 각각 자신의 site 디렉터리에 독립적인 Python 패키지 세트를 설치하는 가벼운 "가상 환경(virtual environments)" 생성을 지원해요. 가상 환경은 기존의 Python 설치(가상 환경의 "기본(base)" Python이라고 함) 위에 생성되며, 기본적으로 기본 환경의 패키지에서 분리되어 가상 환경에 명시적으로 설치된 패키지만 사용할 수 있어요. 버전 3.3에서 추가되었어요.

가상 환경 안에서 사용하면 pip 같은 일반 설치 도구가 명시적으로 지시하지 않아도 Python 패키지를 가상 환경에 설치해요.

출처: Python documentation

본문

가상 환경은 (무엇보다도) 다음과 같은 특징을 가져요:

  • 특정 프로젝트(라이브러리 또는 애플리케이션)를 지원하는 데 필요한 특정 Python 인터프리터와 소프트웨어 라이브러리, 바이너리를 담는 데 사용돼요. 기본적으로 다른 가상 환경과 운영 체제에 설치된 Python 인터프리터 및 라이브러리의 소프트웨어에서 분리돼요.
  • 관례적으로 프로젝트 디렉터리에 .venv 또는 venv로 명명된 디렉터리(또는 ~/.virtualenvs 같은 많은 가상 환경을 위한 컨테이너 디렉터리)에 담겨요.
  • Git 같은 소스 제어 시스템에 커밋되지 않아요.
  • 일회용(disposable)으로 간주돼요 — 처음부터 삭제하고 다시 만드는 것이 간단해야 해요. 환경에 프로젝트 코드를 넣지 않아요.
  • 이동하거나 복사할 수 있다고 간주되지 않아요 — 대상 위치에서 같은 환경을 다시 만들면 돼요.

가용성(Availability): Android, iOS, WASI 아님. 모바일 플랫폼이나 WebAssembly 플랫폼에서는 지원되지 않아요.

가상 환경 생성 (Creating virtual environments)

가상 환경은 venv 모듈을 실행해 생성돼요:

python -m venv /path/to/new/virtual/environment

이 명령은 대상 디렉터리(필요하면 상위 디렉터리 포함)를 만들고, 그 안에 명령이 실행된 Python 설치를 가리키는 home 키가 있는 pyvenv.cfg 파일을 배치해요. 또한 Python 실행 파일의 사본 또는 심볼릭 링크를 포함하는 bin(Windows에서는 Scripts) 하위 디렉터리를 만들고, lib/pythonX.Y/site-packages 하위 디렉터리(Windows에서는 Lib\site-packages)도 만들어요.

주요 옵션:

  • ENV_DIR — 환경을 생성할 디렉터리를 지정하는 필수 인자
  • --system-site-packages — 시스템 site-packages 디렉터리에 대한 접근을 가상 환경에 부여
  • --symlinks — 플랫폼 기본값이 아닐 때 사본 대신 심볼릭 링크 사용 시도
  • --copies — 플랫폼 기본값이 심볼릭 링크여도 사본 사용 시도
  • --clear — 환경 생성 전에 이미 존재하면 환경 디렉터리 내용 삭제
  • --upgrade — Python이 제자리에서 업그레이드되었다고 가정하고 환경 디렉터리를 이 Python 버전으로 업그레이드
  • --without-pip — 가상 환경에 pip 설치 또는 업그레이드 건너뜀(pip는 기본적으로 부트스트랩됨)
  • --prompt <PROMPT> — 이 환경의 대체 프롬프트 접두사
  • --upgrade-deps — 핵심 종속성(pip)을 PyPI의 최신 버전으로 업그레이드
  • --without-scm-ignore-files — 환경 디렉터리에 SCM 무시 파일 추가 건너뜀(Git이 기본 지원)

--without-pip 옵션이 주어지지 않으면 ensurepip가 호출되어 가상 환경에 pip를 부트스트랩해요. 여러 경로를 venv에 줄 수 있으며, 이 경우 각 경로에 주어진 옵션에 따라 동일한 가상 환경이 생성돼요.

가상 환경의 동작 방식 (How venvs work)

가상 환경에서 Python 인터프리터가 실행될 때 sys.prefixsys.exec_prefix는 가상 환경의 디렉터리를, sys.base_prefixsys.base_exec_prefix는 환경 생성에 사용된 기본 Python의 디렉터리를 가리켜요. sys.prefix != sys.base_prefix를 확인하면 현재 인터프리터가 가상 환경에서 실행 중인지 판단할 수 있어요.

가상 환경은 바이너리 디렉터리(POSIX에서는 bin, Windows에서는 Scripts)의 스크립트로 "활성화"될 수 있어요. 활성화는 해당 디렉터리를 PATH 앞에 추가하므로 python을 실행하면 환경의 Python 인터프리터가 호출되고, 설치된 스크립트를 전체 경로 없이 실행할 수 있어요. 활성화 명령은 플랫폼에 따라 달라요(POSIX bash/zsh: source <venv>/bin/activate, Windows cmd.exe: <venv>\Scripts\activate.bat 등).

가상 환경을 사용하기 위해 반드시 활성화할 필요는 없어요. 환경의 Python 인터프리터 전체 경로를 지정해 호출할 수 있고, 환경에 설치된 모든 스크립트는 활성화 없이도 실행 가능해야 해요. 이를 위해 가상 환경에 설치된 스크립트에는 환경의 Python 인터프리터를 가리키는 "shebang" 줄(#!/<path-to-venv>/bin/python)이 있어요.

가상 환경이 활성화되면 VIRTUAL_ENV 환경 변수가 환경의 경로로 설정돼요. 환경에 설치된 스크립트는 환경이 활성화될 것을 기대하면 안 되므로 shebang 줄에 절대 경로가 포함되며, 이 때문에 환경은 일반적으로 이식 불가능(non-portable)해요. 환경을 이동해야 한다면 원하는 위치에서 다시 만들고 이전 위치의 환경을 삭제해야 해요.

API

고수준 메서드는 서드파티 가상 환경 생성자가 자신의 필요에 따라 환경 생성을 맞춤화할 수 있는 간단한 API, EnvBuilder 클래스를 사용해요.

classvenv.EnvBuilder(system_site_packages=False, clear=False, symlinks=False, upgrade=False, with_pip=False, prompt=None, upgrade_deps=False, *, scm_ignore_files=frozenset())

EnvBuilder 클래스는 인스턴스화 시 다음 키워드 인자를 받아요: system_site_packages, clear, symlinks, upgrade, with_pip, prompt, upgrade_deps, scm_ignore_files. EnvBuilder는 기본 클래스로 사용될 수 있어요.

주요 메서드:

  • create(env_dir) — 대상 디렉터리를 지정해 가상 환경을 생성해요.
  • ensure_directories(env_dir) — 환경 디렉터리와 필요한 모든 하위 디렉터리를 만들고, 속성(경로 등)을 담는 컨텍스트 객체를 반환해요. 컨텍스트 객체는 env_dir, env_name, prompt, executable, inc_path, lib_path, bin_path, bin_name, env_exe, env_exec_cmd 속성을 가진 types.SimpleNamespace예요.
  • create_configuration(context) — 환경에 pyvenv.cfg 구성 파일을 생성해요.
  • setup_python(context) — 환경에 Python 실행 파일의 사본 또는 심볼릭 링크를 생성해요.
  • setup_scripts(context) — 플랫폼에 적합한 활성화 스크립트를 가상 환경에 설치해요.
  • upgrade_dependencies(context) — 환경의 핵심 venv 종속성 패키지(현재 pip)를 업그레이드해요.
  • post_setup(context) — 서드파티 구현에서 패키지를 미리 설치하거나 다른 사후 생성 단계를 수행하도록 재정의할 수 있는 자리 표시자 메서드예요.
  • install_scripts(context, path) — 하위 클래스에서 맞춤 스크립트를 가상 환경에 설치하는 데 도움을 주는 메서드예요.
  • create_git_ignore_file(context) — 가상 환경 내에 전체 디렉터리가 Git에 무시되도록 하는 .gitignore 파일을 생성해요.

create() 메서드는 하위 클래스 맞춤화를 위한 훅을 보여줘요: ensure_directories(), create_configuration(), setup_python(), setup_scripts(), post_setup()을 재정의할 수 있어요.

venv.create(env_dir, system_site_packages=False, clear=False, symlinks=False, with_pip=False, prompt=None, upgrade_deps=False, *, scm_ignore_files=frozenset())

주어진 키워드 인자로 EnvBuilder를 만들고 env_dir 인자로 그 create() 메서드를 호출해요.

EnvBuilder 확장 예제

다음 스크립트는 생성된 가상 환경에 setuptools와 pip를 설치하는 하위 클래스를 구현해 EnvBuilder를 확장하는 방법을 보여줘요:

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):
    """이 빌더는 setuptools와 pip를 설치해
    생성된 가상 환경에 다른 패키지를 pip이나 easy_install로 설치할 수 있게 해준다."""
    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):
        """생성 중인 가상 환경에 미리 설치할 패키지 설정"""
        os.environ['VIRTUAL_ENV'] = context.env_dir
        if not self.nodist:
            self.install_setuptools(context)
        # ...

더 알아보기 (Learn more)