상위 목록: 하위 목록: 작성 날짜: 읽는 데 11 분 소요

가상 환경(Virtual Environment)

가상 환경(Virtual Environment)이란 프로젝트마다 독립된 Python 실행 환경과 패키지 설치 공간을 만드는 기능입니다.

제 28강 PIP 설치에서는 pip로 패키지를 설치했습니다. 이 방식으로 설치한 패키지는 Python이 설치된 경로의 site-packages에 저장되며, 모든 프로젝트가 같은 패키지를 공유합니다.

예를 들어 A 프로젝트는 어떤 패키지의 1.16 버전이 필요하고, B 프로젝트는 같은 패키지의 1.17 버전이 필요하다고 가정합니다.

하나의 공간에는 한 버전만 설치할 수 있으므로, B 프로젝트를 위해 패키지를 업그레이드하면 A 프로젝트가 동작하지 않을 수 있습니다.


가상 환경을 사용하면 프로젝트마다 별도의 site-packages를 가지므로, 프로젝트별로 다른 버전의 패키지를 설치할 수 있습니다.

또한 프로젝트에 필요한 패키지 목록만 관리할 수 있어, 다른 컴퓨터에서 같은 환경을 쉽게 재현할 수 있습니다.

Python 3.3 이상부터 표준 라이브러리인 venv 모듈로 가상 환경을 생성할 수 있습니다.

정리하면 가상 환경이 없을 때와 있을 때는 다음과 같이 다릅니다.

구분 가상 환경 없음 가상 환경 사용
패키지 설치 위치 원본 Python의 site-packages 하나 프로젝트마다 별도의 site-packages
버전 충돌 한 프로젝트를 위해 업그레이드하면 다른 프로젝트가 영향을 받음 프로젝트끼리 영향을 주지 않음
패키지 목록 모든 프로젝트의 패키지가 섞여 있음 그 프로젝트에 필요한 패키지만 있음
환경 삭제 패키지를 하나씩 제거해야 함 가상 환경 폴더를 지우면 끝


이번 강좌에서는 venv로 가상 환경을 만들고 활성화하는 방법뿐만 아니라, 가상 환경이 실제로 어떻게 격리되는지를 sys.prefix, site-packages 경로, PATH 환경 변수를 통해 원리 수준에서 확인합니다. 이어서 requirements.txt와 pyproject.toml로 패키지 목록을 관리하는 방법과 Git에서 가상 환경을 다루는 방법을 다룹니다.



가상 환경 생성(venv)

cd 프로젝트_폴더
python -m venv .venv

python -m venv 경로는 지정한 경로에 가상 환경을 생성합니다.

경로는 자유롭게 지정할 수 있지만, 프로젝트 폴더 안에 .venv라는 이름으로 생성하는 것이 일반적입니다.

가상 환경은 명령을 실행한 Python의 버전을 사용합니다. 그러므로 여러 버전의 Python이 설치되어 있다면, 사용할 버전의 Python으로 명령을 실행합니다.

-m venv는 venv 모듈을 스크립트처럼 실행하라는 의미입니다. 명령이 끝나면 별도의 출력 없이 지정한 경로에 폴더가 생성되며, 생성 과정에서 가상 환경에 pip도 함께 설치됩니다.

이름 앞의 점(.)은 macOS·Linux에서 숨김 폴더를 의미하므로, 프로젝트 파일 목록에서 가상 환경 폴더가 눈에 띄지 않게 됩니다. 많은 편집기와 도구가 .venv라는 이름을 자동으로 인식합니다.

  • Tip : macOS·Linux에서는 python 대신 python3 명령을 사용해야 할 수 있습니다.


Windows에서 생성한 .venv 폴더의 구조는 다음과 같습니다.

.venv
├── .gitignore
├── Include
├── Lib
│   └── site-packages
├── pyvenv.cfg
└── Scripts
    ├── activate
    ├── activate.bat
    ├── activate.fish
    ├── Activate.ps1
    ├── deactivate.bat
    ├── pip.exe
    ├── python.exe
    └── pythonw.exe

Lib\site-packages는 가상 환경 전용 패키지 설치 공간이며, 생성 직후에는 pip만 설치되어 있습니다.

Scripts에는 가상 환경용 python.exe, pip.exe와 활성화 스크립트가 저장됩니다.

macOS·Linux에서는 Scripts 대신 bin, Lib\site-packages 대신 lib/python3.x/site-packages 폴더가 생성됩니다.


home = E:\Miniconda
include-system-site-packages = false
version = 3.14.6

pyvenv.cfg는 가상 환경의 설정 파일입니다. 일부를 확인하면 위와 같습니다.

home은 가상 환경을 생성한 원본 Python의 경로이며, 가상 환경은 Python 전체를 복사하지 않고 원본 Python의 표준 라이브러리를 사용합니다.

include-system-site-packages = false는 원본 Python에 설치된 패키지를 사용하지 않는다는 의미입니다.

version은 가상 환경을 만든 Python의 버전입니다. 실제 파일에는 이 밖에도 원본 실행 파일의 경로(executable)와 가상 환경을 만들 때 실행한 명령(command)이 함께 기록됩니다.

이 파일이 가상 환경의 핵심입니다. 뒤의 가상 환경이 격리되는 원리 섹션에서 다루는 것처럼, Python은 시작할 때 이 파일이 있는지 확인해 자신이 가상 환경에서 실행되는지를 판단합니다.

  • Tip : 가상 환경은 원본 Python 경로에 의존하므로, .venv 폴더를 다른 경로나 다른 컴퓨터로 복사해서 사용하지 않습니다. 필요하다면 새로 생성합니다.

  • Tip : python -m venv --system-site-packages .venv로 생성하면 include-system-site-packages = true가 되어, 가상 환경에서도 원본 Python의 패키지를 읽을 수 있습니다. 격리가 약해지므로 특별한 이유가 없다면 사용하지 않습니다.



가상 환경 활성화(activate)

# Windows 명령 프롬프트(cmd)
.venv\Scripts\activate.bat

# Windows PowerShell
.venv\Scripts\Activate.ps1

# Windows Git Bash
source .venv/Scripts/activate

# macOS·Linux (bash, zsh)
source .venv/bin/activate

가상 환경을 사용하려면 먼저 활성화(activate)해야 합니다.

운영 체제와 셸에 따라 실행할 스크립트가 다르며, Windows는 Scripts 폴더, macOS·Linux는 bin 폴더의 스크립트를 실행합니다.

활성화하면 PATH 환경 변수의 맨 앞에 가상 환경의 실행 파일 경로가 추가되므로, python과 pip 명령이 가상 환경의 실행 파일을 가리키게 됩니다.

일반적으로 명령 프롬프트 앞에 (.venv)와 같이 가상 환경 이름이 표시되며, 활성화된 가상 환경의 경로는 VIRTUAL_ENV 환경 변수에 저장됩니다.

  • Tip : PowerShell에서는 실행 정책(Execution Policy) 설정에 따라 Activate.ps1 스크립트 실행이 차단될 수 있습니다.

  • Tip : 활성화하지 않고 .venv\Scripts\python.exe(macOS·Linux는 .venv/bin/python)를 직접 실행해도 가상 환경의 Python이 실행됩니다.


활성화 스크립트가 하는 일은 생각보다 단순합니다. Windows의 activate.bat을 열어 보면 핵심은 다음 몇 줄입니다.

set "VIRTUAL_ENV=C:\project\.venv"
set "_OLD_VIRTUAL_PATH=%PATH%"
set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%"
set "PROMPT=(.venv) %PROMPT%"
  1. VIRTUAL_ENV에 가상 환경 폴더의 경로를 저장합니다.
  2. 비활성화할 때 되돌리기 위해 현재 PATH를 _OLD_VIRTUAL_PATH에 저장해 둡니다.
  3. PATH의 맨 앞에 가상 환경의 Scripts 폴더를 추가합니다.
  4. 프롬프트 앞에 (.venv)를 붙여 활성화 상태임을 표시합니다.

위의 C:\project\.venv는 예시 경로이며, 실제 스크립트에는 가상 환경을 생성한 절대 경로가 그대로 기록됩니다. 이것이 .venv 폴더를 다른 위치로 옮기면 안 되는 또 하나의 이유입니다.

셸은 python 같은 명령을 입력받으면 PATH에 나열된 폴더를 앞에서부터 차례대로 찾아, 처음 발견한 실행 파일을 실행합니다. 활성화로 가상 환경의 Scripts 폴더가 맨 앞에 추가되었으므로, 원본 Python보다 가상 환경의 python.exe가 먼저 발견됩니다.

즉, 활성화는 Python 자체를 바꾸는 것이 아니라 python이라는 명령이 어떤 실행 파일을 가리킬지를 바꾸는 것입니다. 그래서 활성화 상태는 그 셸 창에만 적용되며, 새 터미널을 열면 다시 활성화해야 합니다.


import os
import shutil

cwd = os.getcwd()
print(shutil.which("python"))

scripts = os.path.join(cwd, ".venv", "Scripts")
os.environ["PATH"] = scripts + os.pathsep + os.environ["PATH"]
print(shutil.which("python").replace(cwd, "."))
결과
E:\Miniconda\python.EXE
.\.venv\Scripts\python.EXE

활성화 스크립트가 하는 일을 Python으로 재현한 예제입니다. .venv 가상 환경이 있는 프로젝트 폴더에서 원본 Python으로 실행했으며, 출력을 짧게 하기 위해 현재 폴더 경로를 .으로 바꾸어 출력했습니다.

shutil.which(명령)은 셸과 같은 방식으로 PATH를 앞에서부터 검색해, 명령을 입력했을 때 실행될 파일의 경로를 반환합니다.

첫 번째 줄은 원래의 PATH에서 찾은 원본 Python입니다. PATH 맨 앞에 .venv\Scripts를 추가한 뒤 다시 검색하면, 두 번째 줄처럼 가상 환경의 python.exe가 먼저 발견됩니다. 활성화 스크립트가 셸에서 하는 일이 바로 이것입니다.

  • Tip : 첫 번째 줄의 경로는 PATH에 등록된 Python에 따라 달라집니다.


deactivate

가상 환경 사용을 마치려면 deactivate 명령으로 비활성화(deactivate)합니다.

PATH 환경 변수가 원래대로 복구되며, 다시 원본 Python을 사용합니다.

활성화할 때 저장해 둔 _OLD_VIRTUAL_PATH의 값을 다시 PATH에 넣고, VIRTUAL_ENV를 삭제하는 방식으로 복구합니다. 가상 환경 폴더나 설치한 패키지는 그대로 남아 있으므로, 다시 활성화하면 이전 상태로 이어서 사용할 수 있습니다.

  • Tip : 가상 환경을 완전히 삭제하려면 비활성화한 뒤 .venv 폴더를 지우면 됩니다. 원본 Python에는 아무런 흔적이 남지 않습니다.



가상 환경 확인(sys.prefix)

import os
import sys

print(os.path.basename(sys.prefix))
print(sys.base_prefix)
print(sys.prefix != sys.base_prefix)
결과 (원본 Python)
Miniconda
E:\Miniconda
False

결과 (가상 환경)
.venv
E:\Miniconda
True

현재 실행 중인 Python이 가상 환경인지는 sys 모듈로 확인할 수 있습니다.

sys.prefix는 현재 Python 환경의 경로이며, 가상 환경에서는 가상 환경 폴더(.venv)의 경로를 반환합니다.

sys.base_prefix는 원본 Python이 설치된 경로이며, 가상 환경 여부와 관계없이 같은 값을 반환합니다.

그러므로 두 값이 다르다면 가상 환경에서 실행 중이라는 의미가 됩니다.

같은 코드를 원본 Python과 가상 환경의 Python으로 각각 실행한 결과입니다. 경로는 Python이 설치된 위치에 따라 달라집니다.

  • Tip : 명령줄에서 python -c "import sys; print(sys.prefix)"로 현재 사용 중인 환경을 빠르게 확인할 수 있습니다.



가상 환경이 격리되는 원리

import os
import sys

cwd = os.getcwd()
print("executable  :", sys.executable.replace(cwd, "."))
print("prefix      :", sys.prefix.replace(cwd, "."))
print("base_prefix :", sys.base_prefix)
for path in sys.path:
    if path.endswith(("Lib", "site-packages")):
        print("sys.path    :", path.replace(cwd, "."))
결과 (원본 Python)
executable : E:\Miniconda\python.exe
prefix : E:\Miniconda
base_prefix : E:\Miniconda
sys.path : E:\Miniconda\Lib
sys.path : E:\Miniconda\Lib\site-packages

결과 (가상 환경)
executable : .\.venv\Scripts\python.exe
prefix : .\.venv
base_prefix : E:\Miniconda
sys.path : E:\Miniconda\Lib
sys.path : .\.venv\Lib\site-packages

가상 환경이 패키지를 어떻게 분리하는지 확인하기 위해, 같은 코드를 프로젝트 폴더에서 원본 Python과 가상 환경의 Python으로 각각 실행했습니다. 출력을 짧게 하기 위해 현재 폴더 경로를 .으로 바꾸었고, sys.path에서는 표준 라이브러리 폴더(Lib)와 패키지 폴더(site-packages)만 출력했습니다.

sys.path는 import 문이 모듈을 찾는 폴더 목록입니다. import six를 실행하면 Python은 이 목록의 폴더를 앞에서부터 차례대로 검사해, 처음 발견한 six를 불러옵니다.

결과를 비교하면 다음과 같은 차이가 보입니다.

  1. 원본 Python은 prefix와 base_prefix가 같지만, 가상 환경은 prefix가 .venv로 바뀌었습니다.
  2. 표준 라이브러리 폴더 E:\Miniconda\Lib는 두 환경이 같습니다. 가상 환경은 표준 라이브러리를 복사하지 않고 원본의 것을 그대로 사용합니다.
  3. site-packages는 원본 Python에서는 E:\Miniconda\Lib\site-packages이지만, 가상 환경에서는 .venv\Lib\site-packages입니다. 원본 Python의 site-packages는 목록에 아예 없습니다.

즉, 가상 환경의 격리는 import가 검색하는 폴더 목록에서 원본의 site-packages를 빼고, 가상 환경의 site-packages를 넣는 것으로 이루어집니다.


이 경로들은 Python이 시작할 때 다음 순서로 결정됩니다.

  1. Python 실행 파일은 시작할 때 자신이 있는 폴더나 한 단계 위 폴더에 pyvenv.cfg 파일이 있는지 확인합니다.
  2. 파일이 있으면 그 파일이 있는 폴더(.venv)를 sys.prefix로 설정하고, 파일의 home 값으로 원본 Python을 찾아 sys.base_prefix로 설정합니다.
  3. 표준 라이브러리는 sys.base_prefix를 기준으로, site-packages는 sys.prefix를 기준으로 찾습니다.
  4. include-system-site-packages = false이면 원본 Python의 site-packages는 추가하지 않습니다.

pyvenv.cfg가 없는 원본 Python은 sys.prefix와 sys.base_prefix가 모두 설치 경로가 되므로, 같은 규칙으로 원본의 site-packages를 사용하게 됩니다.

pip 역시 sys.prefix를 기준으로 설치 위치를 정하므로, 가상 환경의 Python으로 실행한 pip는 패키지를 .venv\Lib\site-packages에 설치합니다.

  • Tip : Windows의 .venv\Scripts\python.exe는 원본 실행 파일을 그대로 복사한 것이 아니라, pyvenv.cfg를 읽어 원본 Python을 실행해 주는 작은 실행기입니다. 가상 환경에서 sys._base_executable을 출력하면 원본 실행 파일의 경로를 확인할 수 있습니다.


import sys

print(sys.prefix != sys.base_prefix)

try:
    import six
    print(six.__version__)
except ModuleNotFoundError as e:
    print("ModuleNotFoundError :", e)
결과 (원본 Python)
False
1.17.0

결과 (가상 환경)
True
ModuleNotFoundError : No module named ‘six’

격리가 실제로 동작하는지 확인하는 예제입니다. 원본 Python에는 six 패키지가 설치되어 있고, 가상 환경은 막 생성한 상태입니다.

원본 Python은 자신의 site-packages에서 six를 찾아 버전을 출력합니다. 하지만 가상 환경의 sys.path에는 원본의 site-packages가 없으므로, 같은 컴퓨터에 six가 설치되어 있어도 찾지 못하고 ModuleNotFoundError가 발생합니다.

이처럼 가상 환경은 처음에 비어 있는 상태로 시작하며, 필요한 패키지를 가상 환경 안에 직접 설치해야 합니다. 다음 섹션에서 같은 패키지의 다른 버전을 설치해 봅니다.



프로젝트별 패키지 버전

python -m pip install six==1.16.0

가상 환경을 활성화한 상태에서 pip로 패키지를 설치하면, 가상 환경의 site-packages에만 설치됩니다.

원본 Python에는 six 패키지의 1.17.0 버전이 설치되어 있는 상태에서, 가상 환경에 1.16.0 버전을 설치합니다.

패키지==버전의 형태로 설치할 버전을 지정할 수 있습니다.


import sys
import six

print(sys.prefix != sys.base_prefix)
print(six.__version__)
결과 (원본 Python)
False
1.17.0

결과 (가상 환경)
True
1.16.0

같은 코드를 실행해도 어떤 환경의 Python으로 실행하는지에 따라 서로 다른 버전의 패키지를 불러옵니다.

가상 환경에 패키지를 설치해도 원본 Python의 패키지는 변경되지 않습니다.

앞 섹션의 원리로 설명하면, import six가 원본 Python에서는 E:\Miniconda\Lib\site-packages의 1.17.0을, 가상 환경에서는 .venv\Lib\site-packages의 1.16.0을 찾기 때문입니다. 같은 이름의 패키지가 컴퓨터에 두 버전 존재하지만, 각 Python은 자신의 sys.path에 있는 하나만 볼 수 있습니다.

이렇게 프로젝트 A의 가상 환경에는 1.16.0, 프로젝트 B의 가상 환경에는 1.17.0을 설치하면 강좌의 처음에 예로 든 버전 충돌 문제가 해결됩니다.

  • Tip : 활성화 여부를 헷갈리기 쉬우므로, pip 대신 python -m pip로 실행하면 현재 python과 같은 환경에 패키지가 설치됩니다.

  • Tip : pip와 python이 서로 다른 환경을 가리키면, 패키지를 설치했는데도 import에서 ModuleNotFoundError가 발생하는 혼란이 생깁니다. python -m pip --version을 실행하면 이 pip가 어느 경로의 Python에 연결되어 있는지 출력됩니다.



패키지 목록 저장(requirements.txt)

python -m pip freeze > requirements.txt
requirements.txt
six==1.16.0

pip freeze는 현재 환경에 설치된 패키지와 버전을 패키지==버전 형식으로 출력합니다.

출력 결과를 requirements.txt 파일로 저장하면, 프로젝트에 필요한 패키지 목록을 다른 사람과 공유할 수 있습니다.

가상 환경에는 프로젝트에 필요한 패키지만 설치되어 있으므로, 불필요한 패키지가 목록에 포함되지 않습니다.

원본 Python에서 pip freeze를 실행하면 그동안 다른 프로젝트를 위해 설치한 패키지까지 모두 출력됩니다. 프로젝트마다 가상 환경을 사용하는 것은 정확한 패키지 목록을 얻기 위해서이기도 합니다.

pip freeze는 직접 설치한 패키지뿐만 아니라 그 패키지가 의존하는 패키지까지 정확한 버전으로 기록합니다. 그러므로 이 파일로 설치하면 의존 패키지까지 같은 버전으로 재현됩니다.

  • Tip : >는 명령의 출력을 파일로 저장하는 셸의 기능이며, 같은 이름의 파일이 있으면 덮어씁니다.


python -m venv .venv
python -m pip install -r requirements.txt
결과
Collecting six==1.16.0 (from -r requirements.txt (line 1))
  Using cached six-1.16.0-py2.py3-none-any.whl.metadata (1.8 kB)
Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six
Successfully installed six-1.16.0

다른 컴퓨터에서는 새로운 가상 환경을 생성하고 활성화한 다음, pip install -r requirements.txt로 목록의 패키지를 한 번에 설치합니다.

이를 통해 같은 버전의 패키지로 구성된 환경을 재현할 수 있습니다.

  • Tip : 결과의 Using cached는 이전에 내려받은 파일을 재사용했다는 의미이며, 처음 설치할 때는 Downloading이 표시됩니다.



프로젝트 설정 파일(pyproject.toml)

[build-system]
requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"

[project]
name = "myapp"
version = "0.1.0"
description = "Python 가상 환경 예제"
requires-python = ">=3.12"
dependencies = [
    "six==1.16.0",
]

[project.optional-dependencies]
dev = [
    "pytest",
]

pyproject.toml은 Python 프로젝트의 정보와 의존성을 기록하는 표준 설정 파일입니다.

requirements.txt가 설치할 패키지 목록만 담는다면, pyproject.toml은 프로젝트 이름, 버전, 지원하는 Python 버전, 의존성 등을 함께 관리합니다.

두 파일은 역할이 조금 다릅니다. requirements.txt는 pip freeze의 결과처럼 지금 이 환경을 그대로 재현하기 위한 정확한 버전 목록에 가깝고, pyproject.toml의 dependencies는 이 프로젝트가 동작하려면 무엇이 필요한지를 선언하는 목록입니다. 그래서 pyproject.toml에는 six>=1.16처럼 범위로 작성하는 경우가 많습니다.


테이블 설명
[build-system] 프로젝트를 패키지로 빌드할 때 사용할 도구(빌드 백엔드)
[project] 프로젝트 이름(name), 버전(version), 설명(description) 등 메타데이터
requires-python 프로젝트가 지원하는 Python 버전
dependencies 프로젝트 실행에 필요한 패키지 목록
[project.optional-dependencies] 개발·테스트 등 선택적으로 설치하는 패키지 그룹


python -m pip install .
결과
Successfully built myapp
Installing collected packages: six, myapp

Successfully installed myapp-0.1.0 six-1.16.0

pyproject.toml이 있는 폴더에서 pip install .을 실행하면 프로젝트와 dependencies에 작성한 패키지가 함께 설치됩니다.

pip install ".[dev]"와 같이 입력하면 optional-dependencies의 dev 그룹 패키지까지 함께 설치합니다.

결과는 출력의 마지막 부분입니다. 예제의 프로젝트는 src/myapp/__init__.py 파일을 포함한 구조입니다.


import tomllib

with open("pyproject.toml", "rb") as f:
    config = tomllib.load(f)

print(config["project"]["name"])
print(config["project"]["dependencies"])
print(config["build-system"]["build-backend"])
결과
myapp
[‘six==1.16.0’]
setuptools.build_meta

pyproject.toml은 TOML 형식의 파일입니다.

Python 3.11 이상부터 표준 라이브러리인 tomllib 모듈로 TOML 파일을 읽을 수 있으며, 결과는 사전(Dictionary)으로 반환됩니다.

tomllib.load()는 파일을 바이너리 모드(rb)로 열어서 전달해야 합니다.

  • Tip : tomllib는 읽기 전용 모듈이며, TOML 파일을 작성하는 기능은 제공하지 않습니다.



가상 환경과 Git

.venv 폴더는 Git과 같은 버전 관리 시스템에 올리지 않습니다.

가상 환경에는 운영 체제와 Python 설치 경로에 맞춰 생성된 실행 파일이 포함되어 있어, 다른 컴퓨터에서는 그대로 사용할 수 없습니다.

또한 설치한 패키지 파일이 모두 포함되므로 용량이 크고, 패키지를 설치할 때마다 수많은 파일이 변경됩니다.

그러므로 저장소에는 requirements.txt 또는 pyproject.toml만 올리고, 가상 환경은 각자의 컴퓨터에서 새로 생성합니다.


# Created by venv; see https://docs.python.org/3/library/venv.html
*

Python 3.13 이상부터 venv로 생성한 가상 환경 폴더 안에는 위와 같은 .gitignore 파일이 자동으로 생성됩니다.

*는 폴더 안의 모든 파일을 무시한다는 의미이므로, 별도의 설정 없이도 .venv 폴더가 Git에 추가되지 않습니다.

이 파일을 생성하지 않으려면 python -m venv --without-scm-ignore-files .venv로 생성합니다.

  • Tip : 이전 버전의 Python을 사용하거나 다른 도구로 가상 환경을 생성했다면, 프로젝트의 .gitignore 파일에 .venv/를 직접 추가합니다.



다른 가상 환경 도구

venv 외에도 다양한 가상 환경 도구가 있습니다.

conda는 Anaconda, Miniconda에 포함된 패키지·환경 관리 도구로, Python 패키지뿐만 아니라 Python 자체와 Python 외 라이브러리까지 환경별로 설치할 수 있습니다.

이 밖에도 가상 환경과 의존성 관리를 함께 처리하는 도구들이 있으며, 대부분 pyproject.toml을 기반으로 프로젝트를 관리합니다.

어떤 도구를 사용하더라도 프로젝트마다 독립된 환경을 만들고, 패키지 목록을 파일로 관리한다는 원리는 같습니다.

  • Tip : venv는 Python에 기본으로 포함되어 있으므로 별도의 설치 없이 바로 사용할 수 있습니다.



정리

이름 설명 반환값/특징
python -m venv .venv 가상 환경 생성 명령을 실행한 Python 버전 사용
pyvenv.cfg 가상 환경 설정 파일 원본 Python 경로(home), 시스템 패키지 사용 여부
activate / deactivate 활성화 / 비활성화 PATH 맨 앞에 Scripts(bin) 추가 / 복구
VIRTUAL_ENV 활성화된 가상 환경 경로 활성화 시 설정되는 환경 변수
sys.prefix 현재 환경의 경로 가상 환경에서는 .venv 경로
sys.base_prefix 원본 Python의 경로 가상 환경 여부와 관계없이 같음
sys.path import가 모듈을 찾는 폴더 목록 가상 환경에서는 .venv의 site-packages 포함
python -m pip freeze 설치된 패키지 목록 출력 패키지==버전 형식
pip install -r requirements.txt 목록의 패키지 일괄 설치 같은 버전의 환경 재현
pyproject.toml 프로젝트 정보와 의존성 tomllib로 읽기 (Python 3.11 이상)


가상 환경의 원리는 pyvenv.cfg로 sys.prefix를 바꾸고, 그 결과 import가 검색하는 site-packages를 바꾸는 것입니다. 활성화는 여기에 더해 PATH를 바꿔 python 명령이 가상 환경의 실행 파일을 가리키게 하는 편의 기능입니다.

그러므로 어떤 환경에서 실행되고 있는지 헷갈릴 때에는 sys.prefix를 확인하고, 패키지는 항상 python -m pip로 설치하는 습관을 들이면 대부분의 문제를 피할 수 있습니다.

댓글 남기기