자주 묻는 질문

참고: PyPy에 대해 자주 묻는 질문들.


RPython이란 무엇입니까?

RPython은 프로그래밍 언어, 특히 동적 언어를 위한 인터프리터와 가상 머신을 구현하기 위한 프레임워크입니다.

RPython이 일반적인 파이썬 프로그램을 C로 컴파일할 수 있습니까?

아닙니다, RPython은 Python 컴파일러가 아닙니다.

Python에서는 정적 분석을 통해 프로그램이 다루게 될 타입에 대해 무언가를 증명하는 것이 대체로 불가능합니다. Python에 익숙하다면 이는 명확할 것이지만, 확신이 서지 않는다면 [BRETT]을 참고하십시오.

빠른 Python 프로그램을 원하신다면, 대신 PyPy JIT를 사용하십시오.

[BRETT]Brett Cannon, Localized Type Inference of Atomic Types in Python, http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.90.3231

이 RPython 언어란 무엇인가?

RPython은 Python 언어의 제한된 부분집합입니다. 이는 PyPy 툴체인 내에서 동적 언어 인터프리터를 구현하는 데 사용됩니다. 이러한 제약은 RPython 프로그램의 타입 추론(그리고 궁극적으로는 다른 언어로의 번역(translation))이 가능하도록 보장합니다.

“RPython이다”라는 속성은 개별 함수나 모듈이 아니라 항상 전체 프로그램에 적용됩니다(번역(translation) 도구 체인은 전체 프로그램 분석을 수행합니다). 번역(translation) 도구 체인은 모든 호출을 재귀적으로 따라가며 무엇이 프로그램에 속하고 무엇이 속하지 않는지 알아냅니다.

RPython 프로그램의 제약은 주로 타입을 임의의 방식으로 혼합하는 능력을 제한합니다. RPython은 같은 변수에 서로 다른 두 타입을 바인딩하는 것을 허용하지 않습니다. 이런 면에서 (그리고 다른 몇 가지 면에서도) RPython은 Java와 다소 비슷하게 느껴집니다. RPython에서 허용되지 않는 그 밖의 기능으로는 __init____del__을 제외한 특수 메서드(__xxx__)의 사용과 리플렉션 기능(예: __dict__)의 사용이 있습니다.

RPython에서는 기존 표준 라이브러리 모듈 대부분을 사용할 수 없습니다. 예외는 네이티브 지원이 있는 os, math, time의 일부 함수입니다.

RPython의 제약 사항에 대해 더 알아보려면 RPython 설명을 읽으십시오.

RPython은 Zope의 Restricted Python과 어떤 관련이 있습니까?

아닙니다. Zope’s RestrictedPython는 CPython을 위한 샌드박스 실행 환경을 제공하는 것을 목표로 합니다. PyPy’s RPython은 동적 언어 인터프리터를 위한 구현 언어입니다. 그러나 PyPy는 견고한 sandboxed Python Interpreter도 제공합니다.

일부 독스트링에서 보이는 "NOT_RPYTHON"은 무엇입니까?

함수의 독스트링에 “NOT_RPYTHON”을 넣었는데 RPython 프로그램을 번역(translation)하려는 과정에서 그 함수가 발견되면, 번역(translation) 과정이 중단되고 이를 오류로 보고합니다. 따라서 함수를 “NOT_RPYTHON”으로 표시하여 해당 함수가 결코 분석되지 않도록 할 수 있습니다.

함수를 RPython이 아닌 것으로 표시하는 이 방법은 오래된 것입니다. 새 코드에는 대신 @objectmodel.not_rpython 데코레이터를 사용하십시오.

Python 구문 트리를 그대로 가져다 Lisp로 변환할 수는 없었을까요?

반드시 터무니없는 것은 아니지만, 진정한 PyPy 방식은 아닙니다. 어떤 형태의 타입 추론 없이는 이 Python을 번역(translation)하기가 상당히 어렵습니다.:

a + b

이 Common Lisp보다 상당히 더 효율적인 어떤 것으로도:

(py:add a b)

그리고 타입 추론을 가능하게 하는 것이 바로 RPython의 목적입니다.

#'py:add를 제네릭 함수로 만들어, 주어진 CLOS 구현이 유용한 속도를 낼 만큼 충분히 빠른지 확인해 볼 수 있을 것입니다(다만 강제 변환 규칙이 그전에 당신을 미치게 만들 것 같습니다). – mwh

제 프로그램을 RPython으로 다시 작성해야 합니까?

아니요, 시도해서는 안 됩니다. 무엇보다도, RPython은 인터프리터를 작성하기 위해 설계된 언어입니다. 이는 Python의 제한된 부분집합입니다. 만약 여러분의 프로그램이 인터프리터가 아니라 표준 Python 라이브러리의 어떤 부분이나 어떤 서드파티 라이브러리를 사용하는 것과 같은 “실제 작업”을 하려는 것이라면, 애초에 그것은 RPython이 아닙니다. RPython은 직접 인터프리터를 작성하려는 경우에만 살펴봐야 합니다.

목표가 Python 코드의 속도를 높이는 것이라면, 완전하고 표준을 준수하는 Python 2.7 인터프리터인 일반 PyPy(우연히 RPython으로 작성되어 있습니다)를 살펴보십시오. 코드를 RPython으로 다시 작성할 필요가 없을 뿐만 아니라, 설령 그렇게 하더라도 속도 향상을 전혀 얻지 못할 수도 있습니다.

네, 충분한 노력을 들이면 성능에 민감한 몇 가지 작업을 수행하는 작고 독립적인 RPython 코드 조각을 컴파일하는 것이 가능합니다. 하지만 이 경우는 저희에게 흥미롭지 않습니다. 코드를 RPython으로 다시 작성해야 했다면, 예를 들어 C나 C++, Java로 다시 작성해도 마찬가지였을 것입니다. 이들은 훨씬 더 널리 지원되고, 훨씬 더 잘 문서화된 언어입니다 :-)

위 문단들이 전체 진실은 아닙니다. 그것RPython으로 프로그램을 작성하는 것이 PyPy 위에서 실행하는 것보다 상당히 더 나은 속도를 낼 수 있는 경우가 있다는 점에서 사실입니다. 하지만 PyPy를 이끄는 핵심 그룹의 태도는 “그렇다면 그것을 PyPy에 대한 성능 버그로 보고해 주십시오!”라고 답하는 것입니다.

더 순화된 방식으로 표현하자면 다음과 같습니다. 위의 “안 돼요, 하지 마세요!”는 우리가 신규 참여자에게 건네는 일반적인 경고입니다. 그들은 많은 도움이 필요할 가능성이 높습니다 어떤 곳으로부터든, RPython이 그리 간단하지도 않고 폭넓게 문서화되어 있지도 않기 때문입니다. 하지만 동시에 우리, 즉 PyPy 핵심 그룹의 사람들은 동적 언어용 인터프리터와는 매우 다른 일을 하는 서드파티 프로젝트를 지원하는 데 시간을 투자할 생각이 없습니다 — 그저 우리에게 다른 관심사가 있고 하루에 쓸 수 있는 시간은 한정되어 있기 때문입니다. 그래서 요약하자면, 더 주류이며 많은 사람들에게서 도움을 받을 수 있는 기존 대안들로 신규 참여자를 안내하려 시도하는 것이 공정하다고 생각합니다.

혹시 누군가 정말로 RPython을 홍보하고 싶어 한다면, 얼마든지 환영합니다: 저희는 그런 계획을 적극적으로 막지 않을 것입니다. 예를 들어, GIL에 기반하지 않은 멀티스레딩 지원을 비롯해 RPython을 더 나은 Java 스타일 언어로 만들기 위해 할 수 있는 일들이 많이 있습니다. 하지만 저희는 그것들이 저희와 거의 관련이 없기 때문에 구현하지 않습니다. 이것은 오픈소스이며, 이는 누구나 자유롭게 무엇이든 홍보하고 개발할 수 있다는 뜻입니다. 하지만 이는 동시에 여러분이 저희가 스스로 그 방향으로 나아가지 않기로 선택하는 것을 받아들여야 한다는 뜻이기도 합니다.

RPython 툴체인에는 어떤 백엔드가 있습니까?

현재 유일한 백엔드는 C입니다. 이는 PyPy 인터프리터 전체를 번역(translation)할 수 있습니다. 백엔드에 대해 더 알아보려면 번역(translation) 문서를 참고하십시오.

LLVM을 사용할 수 있습니까?

이론상으로는 그렇습니다. 하지만 저희는 번역(translation) 백엔드나 JIT 백엔드로 이미 5~6번 시도했지만 — 매번 실패했습니다.

더 자세히 설명하면, LLVM을 (정적) 번역(translation) 백엔드로 사용하는 것은 오늘날에는 무의미합니다. C 코드를 생성해 clang으로 컴파일할 수 있기 때문입니다. (PyPy를 clang으로 컴파일하더라도 gcc로 컴파일한 결과보다 더 빠르지는 않다는 점에 유의하십시오.) 이론적으로는 LLVM의 GC 통합에서 추가적인 이점을 얻을 수도 있지만, 이것이 조금이라도 쓸모 있으려면 LLVM 쪽에서 더 많은 작업이 필요합니다. 어쨌든, C 코드 내의 커스텀 프리미티브를 통해 인터페이스할 수 있습니다. (이러한 실험적 백엔드 중 최신 버전은 llvm-translation-backend 브랜치에 있으며, 이는 Linux에서 JIT의 유무와 관계없이 PyPy를 번역(translation)할 수 있습니다.)

반면, 저희의 JIT 백엔드로 LLVM을 사용하는 것도 흥미로워 보입니다 — 하지만 이번에도 시도해 보았으나 실패했습니다: LLVM은 생성된 기계 코드를 패치할 방법이 전혀 없으며, 트레이싱 JIT에는 전혀 적합하지 않습니다. LLVM을 사용하려던 하나의 거대한 메서드 JIT조차도 비슷한 이유로 has given up했습니다; 자세한 내용은 해당 블로그 게시물을 참고하십시오.

따라서 PyPy 핵심 개발자들의 입장은 다음과 같습니다: 누군가 LLVM으로 N+1번째 시도를 하고자 한다면 환영이며, IRC 채널에서 약간의 도움을 받을 수 있지만, 그것이 동작함을 증명할 책임은 그들에게 있습니다.

PyPy 컴파일 시 스왑이 발생하거나 메모리가 부족해지는 문제

이는 (여기여기에) 문서화되어 있습니다. PyPy 위에서 “rpython targetpypystandalone”을 실행하려면 4GB의 RAM이 필요하며, CPython 위에서 실행할 때는 조금 더 필요합니다. 여유 공간이 4GB 미만이면 그냥 영원히 스왑을 계속하거나(스왑 공간이 충분하지 않으면 실패합니다). 그리고 여기서 말하는 여유란 진짜로 비어 있다는 뜻입니다. 즉, 머신에 4GB가 있으면 스왑이 발생합니다.

32비트에서는 수치를 반으로 나누십시오. (최근에 시도해보지는 않았지만, 과거에는 다른 것을 전혀 실행하지 않는 2GB Linux 머신에서 32비트 버전을 컴파일하는 것이 가능했습니다: 예를 들어 Gnome/KDE 없이 말입니다.)

PyPy를 위한 RPython 모듈은 독립적으로 번역(translation)될 수 있습니까?

아닙니다, 인터프리터 전체를 다시 빌드해야 합니다. 이는 두 가지를 의미합니다:

  • 테스트 주도 개발을 사용하는 것이 필수적입니다. 번역(translation)을 시도하기도 전에, 순수 Python으로 모듈을 철저히 테스트해야 합니다. 일단 번역(translation)하고 나면, 수정해야 할 타입 관련 문제가 몇 가지만 남아 있어야 하며, 그 외에는 결과물이 그대로 동작해야 합니다.
  • 둘째, 그리고 아마도 가장 중요한 것은: 애초에 그 모듈을 RPython으로 작성해야 할 정말 타당한 이유가 있습니까? 오늘날에는 순수 Python으로 작성하거나, C 코드를 호출해야 한다면 cffi를 사용하는 등의 대안을 정말로 살펴봐야 합니다.

이 맥락에서 전체 인터프리터를 번역(translation)하는 것과 독립적으로 RPython 모듈을 번역(translation)할 수 있는 것은 그리 중요하지 않습니다. (충분한 노력을 들이면 가능할 수도 있지만, 이는 정말 만만치 않은 작업입니다. 지금으로서는 이를 상당히 가능성이 낮은 일로 간주하십시오.)