자주 묻는 질문¶
Contents
- 자주 묻는 질문
- PyPy란 무엇인가?
- PyPy는 CPython을 그대로 대체할 수 있는 것입니까?
- xyz 모듈이 PyPy에서 동작하지 않습니다: ImportError
- xyz 모듈이 샌드박스화된 PyPy에서 동작하지 않나요?
- C 확장 모듈이 PyPy와 함께 작동합니까?
- PyPy는 어떤 플랫폼에서 실행됩니까?
- PyPy는 어떤 파이썬 버전을 구현합니까?
- PyPy는 GIL을 가지고 있나요? 왜 그런가요?
- numpy, numpypy, micronumpy는 어떤가요?
- numpy를 설치해야 할까요, numpypy를 설치해야 할까요?
- PyPy는 꼬리 호출(Tail Call)에 대해 CPython보다 더 영리합니까?
- PyPy를 위한 확장 모듈은 어떻게 작성하나요?
- PyPy는 얼마나 빠릅니까?
- 저는 3줄짜리 벤치마크를 작성했는데, CPython보다 빠르지 않습니다. 왜 그럴까요?
- JIT가 이미 컴파일된 머신 코드를 덤프하고 다시 로드할 수는 없을까요?
- 타입 어노테이션이 PyPy의 성능에 도움이 될까요?
- 다른 언어에도 Python 외에 PyPy의 번역(translation) 도구 체인을 사용할 수 있나요?
- PyPy 개발에 어떻게 참여할 수 있나요? 스프린트에 참가할 수 있나요?
- OSError: … cannot restore segment prot after reloc… 도움이 필요하신가요?
- 버그는 어떻게 보고해야 하나요?
- PyPy는 왜 Git으로 전환하고 GitHub로 이전했나요?
- PyPy의 Windows 64 지원을 개선하려면 무엇이 필요합니까?
- PyPy는 Python2를 얼마나 오래 지원할 예정인가요?
PyPy란 무엇인가?¶
PyPy는 RPython 번역(translation) 툴체인을 사용하여 Python으로 Python을 재구현한 것입니다.
PyPy는 언어 구현에 있어 생성 용이성, 유연성, 유지보수성, 속도 사이의 트레이드오프에 대한 새로운 답을 찾고자 합니다. 자세한 내용은 저희의 목표와 아키텍처 문서를 참조하십시오.
PyPy는 CPython을 그대로 대체할 수 있는 것입니까?¶
거의 다 됐습니다!
어떤 프로젝트든 가장 걸림돌이 될 가능성이 높은 것은 extension modules에 대한 지원입니다. PyPy는 지속적으로 늘어나는 수의 확장 모듈을 지원하지만, 지금까지는 대부분 표준 라이브러리에 있는 것들만 지원합니다.
언어 기능(내장 타입과 함수 포함)은 매우 정교하며 잘 테스트되어 있으므로, 프로젝트가 확장 모듈을 많이 사용하지 않는다면 PyPy에서도 동작할 가능성이 높습니다.
알려진 차이점은 cpython differences에 나열되어 있습니다.
xyz 모듈이 PyPy에서 동작하지 않습니다: ImportError¶
CPython용으로 설치된 모듈은 PyPy에서 자동으로 사용할 수 없습니다 — 이는 CPython 3.6과 3.7을 모두 설치했을 경우, CPython 3.6용으로 설치된 모듈이 CPython 3.7에서 자동으로 사용할 수 없는 것과 마찬가지입니다. 다시 말해, xyz 모듈을 PyPy 전용으로 별도 설치해야 합니다.
리눅스에서는 apt-get이나 이와 비슷한 패키지 관리자를 사용할 수 없다는 뜻입니다: 이러한 도구는 오직 같은 패키지 관리자가 제공하는 버전의 CPython을 위한 것일 뿐입니다. 그러니 지금은 이것들을 잊고 계속 읽어 나가시기 바랍니다.
요즘에는 xyz가 PyPI에서 제공되고 <pypy> -mpip install xyz로 설치 가능한 경우가 매우 흔합니다. 가장 간단한 방법은 use virtualenv (as documented here)를 사용하는 것입니다. 그런 다음 virtualenv에 진입(활성화)하고 다음과 같이 입력합니다: pypy -mpip install xyz. virtualenv를 모르거나 사용하고 싶지 않다면, pypy -m ensurepip를 실행한 후 로컬에서 pip을 사용할 수도 있습니다. ensurepip module은 저희가 제공하는 PyPy 다운로드에 내장되어 있습니다. pip을 사용할 때의 모범 사례는 항상 <python> -mpip ...와 같이 호출하는 것이지만, 명령줄에서 pip를 직접 호출하고 싶다면 pypy -mensurepip --default-pip를 호출해야 합니다.
C 컴파일러에서 오류가 발생하면, 해당 모듈은 지원되지 않는 기능을 사용하는 CPython C 확장 모듈입니다. See below.
또는, xyz 모듈이 PyPI에서 사용 불가능하거나 virtualenv를 사용하고 싶지 않다면, xyz의 소스 코드를 다운로드하고 zip/tarball의 압축을 해제한 후, 소스 디렉터리 안에서 표준 명령인 pypy -mpip install .을 실행하십시오. (참고: 여기서는 python이 아니라 pypy를 사용합니다.) 전역 설치를 위해서는 평소처럼 sudo와 함께 명령을 실행해야 할 수도 있습니다.
xyz 모듈이 샌드박스화된 PyPy에서 동작하지 않나요?¶
죄송하지만, sandboxed PyPy에서는 어떤 확장 모듈도 임포트할 수 없습니다. 사용 가능한 내장 모듈조차도 매우 제한적입니다. PyPy의 샌드박싱은 훌륭한 개념 증명이며, 제 생각에는 의심할 여지 없이 안전하지만, 어디까지나 개념 증명일 뿐입니다. 현재로서는 의욕 있는 개발자의 작업이 좀 더 필요합니다. 하지만 그때까지는 “순수 Python” 예제, 즉 거의 아무것도 임포트하지 않는(또는 재귀적으로 순수 Python 모듈만 임포트하는) 프로그램에만 사용할 수 있습니다.
C 확장 모듈이 PyPy와 함께 작동합니까?¶
먼저, 일부 리눅스 배포판(예: Ubuntu, Debian)은 PyPy를 여러 개의 패키지로 나눈다는 점에 유의하십시오. “pypy”라는 패키지를 설치하셨다면, 아래 내용이 제대로 동작하려면 “pypy-dev”도 설치해야 할 수 있습니다.
C 확장 모듈(C-API를 사용하여 작성된 모듈)을 지원하므로, 수정 없이 실행됩니다. 이는 PyPy의 1.4 릴리스부터 포함되어 있으며, 지원은 거의 완전합니다. PyPy에서 CPython 확장 모듈은 참조 카운팅(refcounting)을 에뮬레이트해야 하기 때문에 CPython에서보다 훨씬 느린 경우가 많습니다. JIT이 최적화할 수 있는 순수 파이썬 또는 CFFI 버전으로 C 확장을 대체하는 것이 더 빠른 경우가 많습니다. xyz 모듈을 설치하려고 할 때, 해당 모듈에 동일한 코드의 C 버전과 파이썬 버전이 모두 있다면, 먼저 C 버전을 비활성화해 보십시오. 이는 보통 setup.py의 특정 줄을 변경하는 것만으로 쉽게 할 수 있습니다.
ctypes 기반 확장을 완전히 지원합니다. 하지만 최고의 성능을 위해서는 C 코드와의 인터페이스에 cffi 모듈을 사용하는 것을 권장합니다.
refcounting 시맨틱을 관리하는 방법에 대한 자세한 내용은 rawrefcount를 참조하십시오.
PyPy는 어떤 플랫폼에서 실행됩니까?¶
PyPy는 현재 다음을 지원합니다:
- 대부분의 일반적인 운영체제(Linux 32/64비트, Mac OS X 64비트, Windows 32/64비트, OpenBSD, FreeBSD)에서의 x86머신,
- 64비트 AArch, 즉 ARM64는,
- Linux를 실행하는 ARM 하드웨어(VFPv3을 갖춘 ARMv6 또는 ARMv7)(이에 대해서는 더 이상 사전 빌드된 바이너리를 제공하지 않습니다),
- Linux를 실행하는 PPC64의 빅 엔디안 및 리틀 엔디안 변형,
- Linux를 실행하는 s390x
PyPy는 Linux 머신에서 정기적으로 광범위하게 테스트됩니다. Mac과 Windows에서도 동작하며 해당 환경에서도 테스트되지만, 저희 대부분이 Linux를 사용하고 있어 수정 사항은 서드파티 기여에 의존할 수 있습니다.
소스로부터 부트스트랩하려면 PyPy는 CPython 2.7 또는 PyPy 2.7 중 하나를 사용할 수 있습니다. 크로스 번역(translation)은 실제로 지원되지 않습니다. 예를 들어 32비트 PyPy를 빌드하려면 32비트 환경이 필요합니다.
PyPy는 어떤 파이썬 버전을 구현합니까?¶
PyPy는 RPython이 이를 위해 작성되었기 때문에 항상 2.7을 지원합니다. 또한, PyPy는 다양한 Python3 버전을 지원하며, 최신 릴리스는 release notes를 참조하세요. 일반적으로, 우리는 Python3의 한두 버전을 지원합니다.
PyPy는 GIL을 가지고 있나요? 왜 그런가요?¶
네, PyPy에는 GIL이 있습니다. GIL을 제거하는 것은 매우 어렵습니다. CPython 위에서는 두 가지 문제가 있습니다: (1) GC, 이 경우에는 참조 카운팅; (2) Python 언어 전체.
PyPy에서 어려운 문제는 (2)번입니다: 이는 가변 객체가 한 스레드에서 변경되는 동시에 다른 스레드에서 읽히는 경우와 같은 문제를 뜻합니다. 이는 모든 가변 타입에 해당하는 문제입니다: Python 인터프리터 전체에 걸쳐 신중한 검토와 수정(대부분 세밀한 잠금)이 필요합니다. 이는 상당한 노력이 필요하지만, Jython/IronPython이 보여주었듯이 완전히 불가능한 것은 아닙니다. 여기에는 사용자(즉, Python 프로그래머)에게 특정 효과가 괜찮은지 여부에 대한 미묘한 결정도 포함됩니다.
CPython에는 참조 계수(reference counting) 문제 (1)이 추가로 있습니다. PyPy에서는 이 하위 문제가 더 간단합니다: 가비지 컬렉터가 멀티스레드를 인식하도록 만들기만 하면 됩니다. 이는 CPython보다 PyPy에서 효율적으로 수행하기가 더 쉽습니다. 하지만 이는 문제 (2)를 해결하지는 못합니다.
PyPy의 Software Transactional Memory (STM) 버전을 지원하기 위한 작업이 있었다는 점에 유의하십시오. 이는 GIL 없이 동작하면서도 동시에 Python 프로그래머에게는 GIL이 있다는 완전한 착각을 계속 제공하는 대안적인 PyPy를 제공할 것입니다. 이 작업은 자체적인 기술적 어려움으로 인해 현재 다소 정체된 상태입니다.
numpy, numpypy, micronumpy는 어떤가요?¶
2011년으로 거슬러 올라가면, PyPy 팀은 PyPy에서 numpy를 started to reimplement했습니다. 이는 두 가지 부분으로 이루어져 있습니다:
- 내장 모듈 pypy/module/micronumpy: 이는 RPython으로 작성되었으며
numpy.core.multiarray모듈의 내용을 대략적으로 다룹니다. 헷갈리게도, 이는 PyPy에서_numpypy라는 이름으로 사용할 수 있습니다. 이는 기본적으로 PyPy의 모든 공식 릴리스에 포함되어 있습니다 (하지만 향후 제거될 수도 있습니다).- 우리가 유지 관리하며 비공식적으로
numpypy라고 불리는 공식 numpy 저장소의 fork로, upstream numpy와의 주요 차이점은 C로 작성된numpy.core.multiarray대신 RPython으로 작성된 micronumpy 모듈을 기반으로 한다는 것입니다.
numpy를 설치해야 할까요, numpypy를 설치해야 할까요?¶
TL;DR 버전: numpy를 사용해야 합니다. pypy -m pip install numpy로 설치할 수 있습니다.
업스트림 numpy는 C로 작성되었으며, cpyext 호환성 계층에서 실행됩니다. 오늘날 cpyext는 테스트 스위트를 통과할 만큼 충분히 성숙해서, 업스트림 numpy를 그대로 사용할 수 있습니다. numpy의 주된 단점은 cpyext가 악명 높게 느리다는 것이며, 따라서 numpypy보다 성능이 떨어집니다. 하지만 HPy를 사용할 수 있게 되면 동일한 속도에 도달할 것으로 예상되기에, 이를 개선하기 위해 적극적으로 작업하고 있습니다.
반면, numpypy는 RPython으로 작성되어 있어서 JIT에 더 친화적이고 호출 속도가 매우 빠릅니다. 하지만 이는 재구현이며 완전히 호환되도록 만들기는 어렵습니다: 수년에 걸쳐 프로젝트가 서서히 성숙해졌고, 결국 행렬 계산 속도를 높이기 위해 LAPACK과 BLAS 라이브러리를 호출할 수 있게 되었으며, 업스트림 numpy와 약 80%의 동등성에 도달했습니다. 그러나 80%는 100%와는 거리가 멉니다. cpyext/numpy 호환성이 완성되었으므로, numpypy에 대한 지원을 중단했습니다.
PyPy는 꼬리 호출(Tail Call)에 대해 CPython보다 더 영리합니까?¶
아니요. PyPy는 내장 디버거 기능을 포함하여 Python 언어 설계를 따릅니다. 이는 Guido van Rossum이 두 개의 블로그 게시물에서 요약했듯이, 꼬리 호출을 방지합니다. 게다가, JIT도 Stackless도 그것을 바꾸지 않습니다.
PyPy를 위한 확장 모듈은 어떻게 작성하나요?¶
자세한 내용은 Writing extension modules for pypy을 참고하십시오.
PyPy는 얼마나 빠릅니까?¶
이는 실제로 여러분의 코드에 따라 다릅니다. 순수 Python 알고리즘 코드의 경우, 매우 빠릅니다. 좀 더 일반적인 Python 프로그램의 경우 일반적으로 CPython 2.7의 3배 속도를 냅니다. 저희의 benchmarking site와 JIT 문서에 관심이 있으실 수도 있습니다.
Your tests are not a benchmark: 테스트는 PyPy에서 느린 경향이 있습니다. 정확히 한 번만 실행되기 때문이며, 좋은 테스트라면 코드의 다양한 예외 상황(corner case)을 검사하기 때문입니다. 이는 JIT 컴파일러에게 나쁜 경우입니다. 또한 저희의 JIT은 워밍업 비용이 매우 높다는 점에 유의하시기 바랍니다. 즉, 모든 프로그램은 시작 시점에 느립니다. CPython과 시간을 비교하고 싶다면, 비교적 단순한 프로그램이라도 최소한 1초는 실행되어야 하며, 가급적 최소 몇 초 정도는 실행되는 것이 좋습니다. 크고 복잡한 프로그램은 JIT을 워밍업하는 데 훨씬 더 많은 시간이 필요합니다.
저는 3줄짜리 벤치마크를 작성했는데, CPython보다 빠르지 않습니다. 왜 그럴까요?¶
세 줄짜리 벤치마크는 아무것도 하지 않는 벤치마크이거나(이 경우 PyPy가 CPython보다 훨씬 빠를 가능성이 높습니다), 더 흔히는 대부분의 시간을 C로 작업을 수행하는 데 소비하는 벤치마크입니다.
예를 들어, 하나의 복잡한 SQL 연산을 반복적으로 실행하는 루프는 SQL 데이터베이스의 성능만을 측정하게 됩니다. 마찬가지로, 피보나치 수열의 많은 원소를 계산하면 매우 큰 정수가 만들어지므로, 이는 긴 정수 라이브러리의 성능만을 측정하게 됩니다. 이 라이브러리는 CPython에서는 C로, PyPy에서는 RPython으로 작성되어 있지만, 결국 같은 이야기로 귀결됩니다.
PyPy는 Python으로 작성된 코드의 실행 속도를 높입니다.
JIT가 이미 컴파일된 머신 코드를 덤프하고 다시 로드할 수는 없을까요?¶
아니요, 그렇게 할 방법을 찾지 못했습니다. JIT는 다수의 상수 주소를 포함하는 머신 코드를 생성합니다 — 이 주소는 머신 코드가 생성되는 시점에는 상수입니다. 그 대다수는 실행 파일에서 멋진 링크 이름을 가진 채로 찾아볼 수 있는 상수가 전혀 아닐 것입니다. 예를 들어, Python 클래스의 주소는 항상 사용되지만, Python 클래스는 실행 파일에서 정적으로 오는 것이 아닙니다. 프로그램을 다시 시작할 때마다 새로 생성됩니다. 이는 이전(이제는 죽은) 프로세스의 주소를 새 프로세스의 주소로 매핑하는 매우 고급한 방법 — (이제는 죽은) 객체에 대한 모든 이전 가정이 새 객체에 대해서도 여전히 참인지 확인하는 것을 포함하여 — 이 없다면, 머신 코드를 저장하고 다시 불러오는 것을 완전히 불가능하게 만듭니다.
타입 어노테이션이 PyPy의 성능에 도움이 될까요?¶
성능 향상을 위해 제안되고 있는 타입 어노테이션의 두 가지 예는 Cython types와 PEP 484 - Type Hints입니다.
Cython types는 구조적으로 C 선언과 유사합니다. 예를 들어, 지역 변수나 인스턴스 속성은 머신 워드를 사용하도록 강제하기 위해 "cdef int"로 선언할 수 있습니다. 이는 일반적인 파이썬 의미론을 변경합니다(예: 오버플로 검사가 없고, 그곳에 다른 타입의 객체를 쓰려고 하면 오류가 발생합니다). 이는 약간의 추가 성능을 제공하지만, 정확한 이점은 명확하지 않습니다. 예를 들어 지금(2015년 1월) 우리는 사용자가 제공하는 "cdef int" 없이도 그 이점의 일부를 제공하면서, 머신 워드 정수를 인스턴스에 직접 저장하는 기법을 조사하고 있습니다.
반면 PEP 484 - 타입 힌트는 성능을 고려한다면 거의 완전히 쓸모가 없습니다. 먼저, 이름에서 알 수 있듯이 그것들은 힌트일 뿐입니다: PEP 484가 말하듯이 여전히 런타임에 검사되어야 합니다. 아니면 타입 애너테이션이 잘못되었을 때 매우 알아보기 힘든 크래시가 발생하는 방식에도 만족하실 수 있을지 모릅니다. 하지만 그런 경우라도 속도상의 이점은 극히 미미할 것입니다.
그 이유는 여러 가지입니다. 그중 하나는 애너테이션이 잘못된 수준에 있다는 것입니다(예를 들어, PEP 484의 “int”는 Python 3의 int 타입에 대응하는데, 이는 반드시 하나의 머신 워드 안에 들어맞는 것은 아닙니다; 설상가상으로 “int” 애너테이션은 임의의 int 서브클래스도 허용합니다). 다른 하나는 좋은 코드를 생성하려면 훨씬 더 많은 정보가 필요하다는 것입니다(예를 들어, “여기서 호출된 이 f()는 실제로는 저기 있는 이 함수를 의미하며, 절대 몽키 패치되지 않을 것이다” – 그런데 len()이나 list()도 마찬가지입니다). 세 번째 이유는 PyPy의 JIT 트레이스에 있는 일부 “가드(guard)”에는 명백히 대응하는 타입이 없다는 것입니다(예를 들어, “이 dict는 지금까지 __hash__를 오버라이드하지 않는 키를 사용해왔으므로 더 효율적인 구현이 사용되었다”). 많은 가드(guard)들은 타입과 아무런 대응 관계조차 없습니다(“이 클래스 속성은 수정되지 않았다”; “루프 카운터가 0에 도달하지 않았으므로 GIL을 해제할 필요가 없다” 등).
현재 PyPy가 작동하는 방식대로라면, PEP 484가 제공할 수 있는 것보다 훨씬 더 유용한 정보를 유도해낼 수 있으며, 이는 자동으로 이루어집니다. 저희가 아는 한, PyPy에 빠른 1차 패스(first-pass) JIT와 같은 다른 기법을 추가하더라도 이는 마찬가지입니다.
다른 언어에도 Python 외에 PyPy의 번역(translation) 도구 체인을 사용할 수 있나요?¶
네. PyPy 인터프리터를 번역(translation)하는 툴슈트는 상당히 범용적이어서, Python뿐만 아니라 어떤 언어에 대해서도 최적화된 버전의 인터프리터를 만드는 데 사용할 수 있습니다. 물론 이러한 인터프리터들은 PyPy가 Python에 제공하는 것과 동일한 기능들, 즉 다양한 언어로의 번역(translation), 스택리스(stackless) 기능, 가비지 컬렉션, 임의 정밀도 정수와 같은 다양한 것들의 구현 등을 활용할 수 있습니다.
현재 우리는 Ruby 인터프리터인 Topaz, PHP 인터프리터인 Hippy, (Leonardo Santagada가 Summer of PyPy 프로젝트로 작업한) JavaScript interpreter의 초기 버전, (Carl Friedrich Bolz가 학사 논문으로 작업한) Prolog interpreter, 그리고 (스프린트 동안 만들어진) SmallTalk interpreter를 갖고 있습니다. 또한 미완성된 Scheme구현도 있습니다.
PyPy 개발에 어떻게 참여할 수 있나요? 스프린트에 참가할 수 있나요?¶
물론 스프린트에 참가하실 수 있습니다! 저희는 언제나 새로운 참가자를 환영하며, 프로젝트를 시작하는 데 최대한 도움을 드리려고 노력합니다. 저희는 튜토리얼을 제공하고, 경험이 풍부한 PyPy 개발자와 짝을 지어 드립니다. 새로운 참가자는 스프린트에 오기 전에 어느 정도의 Python 경험이 있고 PyPy 문서 일부를 읽어 두어야 합니다.
스프린트에 참가하는 것이 보통 PyPy 개발에 입문하는 가장 좋은 방법입니다. 막히거나 조언이 필요하면 문의하세요. IRC는 피드백을 가장 즉각적으로 얻을 수 있는 방법이고(적어도 하루 중 일부 시간대에는 그렇습니다; 대부분의 PyPy 개발자가 유럽에 있습니다), 긴 논의에는 mailing list가 더 낫습니다.
또한 https://github.com/pypy/pypy 의 GitHub 저장소를 통한 참여도 권장합니다. 이슈는 issue tracker에서 제출하고 논의할 수 있으며, pull requests도 환영합니다.
OSError: … cannot restore segment prot after reloc… 도움이 필요하신가요?¶
Linux에서 SELinux가 활성화되어 있으면 “OSError: externmod.so: cannot restore segment prot after reloc: Permission denied.”와 비슷한 오류가 발생할 수 있습니다. 이는 설정 과정에서 C 컴파일러를 약간 편법으로 사용하기 때문이며, root 권한으로 다음 명령을 실행하면 비활성화할 수 있습니다:
# setenforce 0
이렇게 하면 SELinux의 보호 기능이 비활성화되어 PyPy가 올바르게 설정될 수 있습니다. 필요하다면 반드시 다시 활성화하시기 바랍니다!
버그는 어떻게 보고해야 하나요?¶
저희 버그 트래커는 여기에 있습니다: https://github.com/pypy/pypy/issues/
빠진 기능이나 CPython과의 비호환성은 버그로 간주되며, 이러한 버그 제보는 환영합니다. (저희의 알려진 비호환성 목록도 참고하십시오.)
“PyPy 충돌이 발생하거나 이상한 예외가 발생합니다” 유형의 버그에 대해서는, 다음을 유의해 주십시오: 저희가 직접 버그를 재현하지 못하면 아무것도 할 수 없습니다. 저희는 gdb의 트레이스백이나 코어 덤프로는 아무것도 할 수 없습니다. 이는 표준 PyPy가 디버그 심볼 없이 컴파일되기 때문만은 아닙니다. 진짜 이유는 C 수준 트레이스백이 PyPy에서는 보통 전혀 도움이 되지 않기 때문입니다. PyPy를 디버깅하는 것은 성가실 수 있습니다.
이것은 명확하고 유용한 버그 리포트입니다. (사실, 때로는 문제를 재현하기 정말 어려운 경우도 있지만, 그래도 시도해 보시기 바랍니다.)
좀 더 자세히 설명하면:
- 먼저 정확한 PyPy 버전과 OS를 알려주세요.
- 버그가 “
pypy --jit off”에서 재현되는지 알면 검색 범위를 좁히는 데 도움이 될 수 있습니다. “pypy --jit off”가 항상 작동한다면, 문제는 JIT에 있을 수 있습니다. 그렇지 않다면, 그 부분은 무시해도 된다는 것을 알 수 있습니다. - 오픈 소스 구성 요소만으로 버그를 발견하셨다면, 저희가 직접 문제를 재현해볼 수 있도록 단계별 안내를 제공해 주시기 바랍니다. PyPy 외의 다른 프로그램에 대해 저희가 무언가 알고 있으리라고 가정하지 말아 주십시오. 저희는 (추측하거나 스스로 알아낼 필요 없이) 한 단계씩 그대로 따라 할 수 있는 안내를 원합니다. 이는 귀하의 것과 유사한 머신에서 순정 PyPy부터 시작해 동일한 문제가 나타날 때까지 진행하는 것입니다. (가능하다면 단계 수와 실행에 걸리는 시간을 줄여보셔도 좋지만, 필수는 아닙니다.)
- 버그가 비공개 소스(Closed Source) 컴포넌트와 관련되어 있거나, 저희가 직접 설치하기에는 오픈 소스 컴포넌트가 너무 많은 경우라면, 버그를 재현할 수 있는 머신에 대한 임시 ssh 접근 권한을 저희에게 제공해 주실 수 있을 것입니다. 혹은, 문제가 발생하는 VirtualBox나 VMWare 가상 머신을 저희가 다운로드할 수도 있을 것입니다.
- 만약 저희에게 접근 권한을 제공하는 데 ssh 이외의 도구를 사용하거나, 약속을 잡거나, NDA에 서명해야 한다면, 소액의 상용 지원 계약을 고려해볼 수 있습니다.
- 그것조차 불가능하시다면, 죄송하지만 저희가 도와드릴 수 없습니다.
물론 직접 문제를 디버깅해 볼 수도 있고, #pypy IRC 채널에서 질문하시면 저희가 시작하는 것을 도와드릴 수도 있습니다. 하지만 각오하셔야 합니다: 성가신 PyPy 문제를 디버깅하는 것은 보통 자동 생성된 C 코드에서 상당히 많은 gdb 작업이 필요하며, PyPy 자체의 RPython 소스 코드부터 GC, 그리고 어쩌면 JIT까지 관련된 다양한 구성 요소에 대한 최소한의 지식도 필요합니다.
PyPy는 왜 Git으로 전환하고 GitHub로 이전했나요?¶
PyPy는 2010년에 SVN에서 Mercurial and bitbucket으로 이전했습니다. 2020년, bitbucket이 Mercurial 지원을 전격 중단했을 때, 우리는 Git/GitHub로 이전할지 논의했습니다. 당시 우리는 (1) Git 워크플로가 우리 스타일에는 Mercurial 워크플로만큼 적합하지 않으며, (2) “다른 사람들도 다 하니까”라는 이유만으로 GitHub로 이전하는 것은 근거가 빈약하다는 결론을 내렸습니다.
(1)에 대해서는 몇 가지 문제가 있지만, 아마 가장 중요한 것은 PyPy 저장소에 수천 개의 이름이 붙은 브랜치가 있다는 점입니다. Git에는 이에 상응하는 개념이 없습니다. 물론 Git에도 브랜치가 있는데, 이는 Mercurial에서는 북마크라고 불립니다. 우리는 북마크에 대해 이야기하는 것이 아닙니다.
git 브랜치와 이름 붙은 브랜치의 차이는, (아무리 크더라도) 브랜치가 10개인 저장소에서는 그다지 중요하지 않습니다. 하지만 PyPy의 경우, 그 당시 브랜치가 1840개나 있었습니다. 물론 대부분은 지금은 닫혀 있습니다. 하지만 우리는 (지금도, 그리고 앞으로도) 과거의 커밋을 보고 그것이 어느 브랜치에서 만들어졌는지 알아낼 수 있는 능력을 정말로 유지하고 싶습니다. Git 브랜치와 Mercurial 브랜치 사이에는 차이가 있으며, 이는 Git으로 항상 가능한 것은 아닙니다— 우리는 열심히 찾아봤지만, 이 워크플로우를 얻을 수 있는 내장된 방법은 없습니다.
아직도 확신이 안 서시나요? 커밋 3개가 있는 이런 git 저장소를 생각해 봅시다: 커밋 #2는 부모가 #1이고 git 브랜치 “A”의 head이며, 커밋 #3 역시 부모가 #1이지만 git 브랜치 “B”의 head입니다. 커밋 #1이 만들어졌을 때, 그것은 브랜치 “A”에 속했을까요, 아니면 “B”에 속했을까요? (head가 마찬가지로 앞으로 이동한 또 다른 브랜치에 속했을 수도 있고, 아예 완전히 삭제되었을 수도 있습니다.)
이 논의 직후, 우리는 각 git 커밋에 출처 브랜치를 나타내는 노트를 주석으로 달 수 있게 해주는 git notes를 발견했습니다. 완벽한 해결책은 아니지만, 어느 정도 충격을 완화해줍니다.
개발 노력의 방향은 PyPy를 오픈소스 프로젝트 공간에 통합하는 쪽으로 전환되었습니다: PyPy는 conda-forge에서의 제공을 포함하여 여러 인기 있는 파이썬 프로젝트에서 테스트되기 시작했습니다. 이는 다른 개발 그룹과의 상호작용에서 마찰을 줄이는 것이 중요해졌다는 것을 의미했습니다. 그들 대부분이 Git만 사용하는 GitHub를 사용한다는 것이 드러났습니다. 그래서 2023년 말에 우리는 주요 개발을 위해 moved to Git/GitHub했습니다. 공개적인 상호작용이 그만큼 많지 않은 저장소들은 여전히 https://foss.heptapod.net/pypy/ 에 남아 있습니다.
PyPy의 Windows 64 지원을 개선하려면 무엇이 필요합니까?¶
PyPy 7.3.5부터 PyPy는 Windows 64비트를 지원합니다. 그 플랫폼에서만 유독 sizeof(long) != sizeof(void *)이고, RPython의 근간이 되는 데이터 타입이 long이기 때문에, 이는 까다로운 문제로 드러났습니다. 이제 그 고비는 넘긴 것으로 보이며, Windows 버전을 CPython과 동등한 수준으로 만드는 데 도움을 환영합니다. 특히, 저희는 winconsoleio, Windows 감사 이벤트, Windows faulthandler와 같은 Windows 전용 기능을 아직 지원하지 않습니다. 성능은 Linux64보다 뒤처질 수 있으며, wininstaller 브랜치는 아직 미완성 상태입니다.
도움을 환영합니다!
PyPy는 Python2를 얼마나 오래 지원할 예정인가요?¶
RPython은 Python2를 기반으로 만들어져 있고 이것이 바뀔 가능성은 극히 낮기 때문에, PyPy의 Python2 버전은 PyPy 자체가 존재하는 한 “영원히” 존재할 것입니다.