pixi

computer-tool
coding
python
virtual-env
의존성 지옥을 벗어날 또 다른 방법
Author

JS HUHH

Published

August 27, 2023

TL; DR

의존성이라는 지옥을 벗어나보자.

넋두리

심각한 프로젝트를 하지 않는다면 ’의존성’이 문제가 되지 않을 수 있다. 하지만 습관을 잘 들여놓아야 심각한 상황이 왔을 때 대처가 가능한 법이다. 지난 번 소개했던 Rye와 유사한 의존성 관리 도구 pixi를 소개한다. 아직 초기 프로젝트지만 개인 프로젝트인 Rye와 달리 pixi는 조금 더 체계적인 지원 체계를 갖출 듯 싶다. OS 플랫폼 별로 별도의 의존성 등을 할당할 수 있는 대목이 가장 마음에 들었다.

파이썬을 위한 많은 의존성 관리 도구가 있지만 선택이 간단하지는 않다. 일단 많은 도구가 OS를 탄다. 그리고 의존성 관리에 필수적인 가상 환경에도 (안타깝지만) ’대세’가 없다. 이렇다보니 조합이 이래저래 복잡해진다. 본격적으로 쓰려면 Poetry 같은 녀석을 부려야 하겠지만, 내가 타협할 수 있는 (문과적 수준의) 선택지가 있었으면 했다. Rye와 pixi가 딱 그 용도로 적합하다.

단점이 아예 없는 것은 아니다. 서비스가 anaconda 패키지 관리 시스템에 의존하기 때문에 필요한 패키지가 사용 환경에서 아나콘다 생태계에 없다면 어쩔 수 없이 타협해야 한다. 0.8 버전부터 PyPI 패키지를 설치할 수 있다. 물론 PyPI 설치의 경우 초기 개발 단계라서 버그가 많다. 그래도 개인 프로젝트를 위한 의존성 관리 도구로는 충분하다.

개발팀은 Rust의 cargo 명령어를 지향한다고 하며, pixi가 언어에 종속되지는 않으나 의존성 지옥에 가장 취약한 python과 궁합이 잘 맞을 것이라고 밝히고 있다. conda-forge를 기본 패키지 저장소로 쓴다는 점부터 pixi가 python을 위한 의존성 관리 도구라는 것을 알 수 있다. 혹시나 해서 julia를 태워 봤다. conda-forge를 통해서 지원되는 julia는 intel macos와 linux다. 이 환경에서는 잘 돌아가고 WSL에서도 잘 설치된다. 콘다-포지의 줄리아 리포지토리에는 Windows와 Silicon mac용 설치 파일이 없다.

설치

https://prefix.dev/docs/pixi/overview#installation

OS에 따라서 설치 방법이 제공된다. macos나 linux라면 brew를 쓰는 것을 권장한다.

brew install pixi # for Macos or linux
iwr -useb https://pixi.sh/install.ps1 | iex # For Windows PowerShell

활용

Rye와 거의 비슷하다.

  • 환경을 프로젝트 폴더 안에 활성화한다.
  • 활용한 언어를 포함해서 필요한 패키지를 add한다.
  • 코딩한다.

Rye든 pixi든 사실 문법 자체는 대체로 Poetry를 따르고 있다.

pixi의 경우 다음과 같은 특징을 지닌다.

  • conda 환경을 따른다.
  • 별도의 셸 환경을 제공한다.

예를 들어보자. 원하는 폴더에 파이썬 환경을 만들고 여기에 pandas와 plotly를 설치하고 싶다고 하자. 해당 폴더를 만들고 터미널을 통해 해당 폴더에 들어가자.

> pixi init .  # 폴더를 생성하고 싶다면 pixi init {프로젝트-이름}
> pixi add python pandas plotly 

pixi가 필요한 패키지를 콘다 리포지터리에서 끌어와 설치한다. 만일 터미널에서 활용하고 싶다면 pixi shell을 치면 된다. pixi를 치면 필요한 명령어를 보여준다.

Multi platform

pixi의 장점은 os별로 구별해서 패키지를 관리할 수 있다는 것이다. 환경을 담고 있는 pixi.toml을 열어보면 이 점을 쉽게 알 수 있다.

[project]
# Default project info....
# A list of platforms you are supporting with your package.
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"]

pixi.toml을 열어보면 프로젝트의 메타 데이터로 플랫폼이 있다. 여기에 정의되어 있지 않은 환경에서 .toml에 정의된 패키지를 인스톨해보자.

 pixi install
  × the project is not configured for your current platform
   ╭─[pixi.toml:6:1]
 6 │ channels = ["conda-forge"]
 7 │ platforms = ["osx-arm64"]
   ·             ────────────────┬────────────────
   ·                             ╰── add 'win-64' here
 8
   ╰────
  help: The project needs to be configured to support your platform (win-64).

이렇게 메시지를 띄워준다. pixi.toml 파일을 열어 해당 플랫폼을 추가한 후 다시 pixi install을 실행하면 된다. 만일 에러가 뜬다면 셸 창을 다시 실행하자. 플랫폼 별 의존성을 세밀하게 정의해 설치하거나 이를 pixi.toml에 지정할 수 있다. 바로 이어서 살펴볼 것이다.

자세한 것은 여기를 참고하도록 하자.

GitHub를 통해 여러 플랫폼에서 코드를 반복 사용하는 경우를 생각해보자. .pixi/env 아래 폴더에 바이너리 및 패키지가 저장된다. 만일 GitHub를 통해 .ignore를 설정했다면 env 아래 폴더가 모두 무시되므로 플랫폼 별로 다른 바이너리가 GitHub로 동기화되지는 않는다.

Example

아마도 멀티플랫폼 지원이 pixi의 가장 큰 장점이 아닐까 싶다. pytorch를 인스톨하는 경우를 떠올려보자.

  • 플랫폼A: Windows + Nvidia GPU
  • 플랫폼B: macos + Silicon mac

하나의 pixi.toml 파일을 통해서 각기 다른 플랫폼에서 파이토치 프로젝트를 유지하는 것이 목표이다. 특히 플랫폼A에서는 cuda를 활용할 예정이다.

pixi.toml
[project]
name = "pixi_pytorch"
version = "0.1.0"
description = "Add a short description here"
authors = ["Junsok Huhh <anarinsk@gmail.com>"]
channels = ["pytorch", "nvidia", "conda-forge"]
platforms = ["win-64", "osx-arm64"]

[tasks]

[target.win-64.dependencies]
pytorch-cuda = "11.8.*"
torchaudio = "2.0.2.*"
pytorch = "2.0.1.*"
torchvision = "0.15.2.*"

[target.osx-arm64.dependencies]
pytorch = "2.0.1.*"
torchvision = "0.15.2.*"

[dependencies]
jupyter = "1.0.0"
  • target은 플랫폼별로 특화된 분기를 지정할 수 있다.
    • .이후 플랫폼, 그리고 지정할 pixi 영역이 붙는다.
    • 지정 가능한 pixi 영역은 activation, dependencies, tasks 세 가지이다.
  • 위 예시 파일을 살펴보자.
    • pixi.toml을 플랫폼A에서 실행하면 .pixi\ 폴더 아래 cuda 기반의 파이토치가 설치된다. 플랫폼B에는 .pixi/ 아래 실리콘 맥 기반의 MPS를 활용한 파이토치가 설치된다.
    • 채널은 플랫폼 별로 구별할 필요가 없다. 플랫폼A는 pytorch, nvidia를 쓰고 플랫폼B는 pytorch 채널을 쓴다.

PyPI 패키지 설치

conda 리포가 대체로 문제가 되지 않지만, matplotlib, stargazer 등은 현재로서는 PyPI로만 설치할 수 있다. 다행히 0.8 버전부터 PyPI 패키지를 설치할 수 있게 되었다. 방법은 두 가지다. (결국은 같은 방법이긴 하다.) 아래 같이 toml 파일을 업데이트하고, pixi install을 실행한다.

PyPI 패키지란 파이썬 패키지 인덱스를 의미한다. 파이썬에서 표준적으로 패키지를 설치하는 명령어인 pip를 통해 설치되는 패키지를 의미한다.

pixi.toml
[pypi-dependencies]
koreanize-matplotlib = "==0.1.1"
stargazer = "*"

아직 실험적인 개발 단계라서 버전 지정 방법 등이 conda와 다르다. *의 경우 최신 버전을 설치한다.

아니면 터미널 창에서 아래와 같이 실행하자. 이 내용은 pixi add --help로도 확인할 수 있다.

$ pixi add --pypi koreanize-matplotlib stargazer

유연함

pixi init을 실행하면 .pixi/.gitignore 포함된다. 즉 작업 환경의 메타 데이터만 남고 해당 작업 환경 자체는 git에 동기화되지 않는다.

필요한 경우 리포를 동기화한 후 pixi install을 실행하면 해당 환경이 그대로 복원된다. 디렉토리 별로 나누어 운용할 수도 있기 때문에 매우 가볍고 유연하게 작업 환경을 부릴 수 있다.

VS Code

VS Code에서 .ipynb로 작업하고 싶다면 간단하다. 윈도의 경우 해당 폴더가 작업 폴더로 잡혀 있다면 커널 선택 시 .pixi... 아래 설치된 커널이 바로 선택가능할 것이다. 만일 그렇지 않다면 커널을 직접 선택해주면 된다.

VS Code에서 파일 > 작업 영역에 폴더 추가를 통해 작업 폴더를 지정할 수 있다. 터미널의 해당 폴더에서 code .을 실행해도 된다.

인터프리터 경로 설정

F1 > Python: 인터프리터 선택 > +인터프리터 경로 입력...

해당 프로젝트 폴더 안에 .pixi로 가자. OS 별로 구별해서 파이썬 바이너리 혹은 스크립트를 선택하면 된다.

  • (macos) .pixi/env/bin/pyhon
  • (windows) .pixi\env\python.exe

실제 응용

아래 리포에서 pixi.toml을 살펴보시라.

References

https://prefix.dev/blog/launching_pixi