Python을 WebAssembly로 컴파일


90

Python 2.7 코드를 웹 어셈블리로 변환하는 것이 가능하다는 것을 읽었지만 그 방법에 대한 확실한 가이드를 찾을 수 없습니다.

지금까지 Emscripten과 필요한 모든 구성 요소를 사용하여 웹 어셈블리에 C 프로그램을 컴파일 했으므로 작동하고 있음을 알고 있습니다 (사용 된 가이드 : http://webassembly.org/getting-started/developers-guide/ )

Ubuntu 컴퓨터에서이 작업을 수행하기 위해 수행해야하는 단계는 무엇입니까? 파이썬 코드를 LLVM 비트 코드로 변환 한 다음 Emscripten을 사용하여 컴파일해야합니까? 그렇다면 어떻게해야합니까?




1
Pyodide는 WebAssembly를 통해 브라우저에 Python 런타임을 제공합니다. github.com/iodide-project/pyodide
guettli

답변:


146

WebAssembly 대 asm.js

먼저, 원칙적으로 WebAssemblyasm.js어떻게 다른지 , 기존 지식과 도구를 재사용 할 가능성이 있는지 살펴 보겠습니다 . 다음은 꽤 좋은 개요를 제공합니다.

요약하자면 WebAssembly ( 대략 로드맵에 더 많은 것이 있으므로 MVP ) :

  • 기존 JavaScript 엔진 (따라서 JIT 가능 또는 컴파일 된 AOT)에 의해 실행될 수있는 정적 유형이있는 AST의 이진 형식입니다.
  • 10-20 % 더 간결하고 (gzipped 비교) JavaScript보다 훨씬 빠르게 구문 분석 할 수 있습니다.
  • JavaScript 구문에 맞지 않는 더 낮은 수준의 작업을 표현할 수 있으며 asm.js를 읽을 수 있습니다 (예 : 64 비트 정수, 특수 CPU 명령, SIMD 등).
  • asm.js에서 (어느 정도) 변환 가능합니다.

따라서 현재 WebAssembly는 asm.js의 반복이며 C / C ++ (및 유사한 언어) 만 대상으로합니다.

웹에서의 Python

GC가 Python 코드가 WebAssembly / asm.js를 대상으로하는 것을 막는 유일한 방법은 아닌 것 같습니다. 둘 다 파이썬 코드를 (실제적으로) 표현할 수없는 저수준 정적으로 형식화 된 코드를 나타냅니다. 현재 WebAssembly / asm.js의 툴체인은 LLVM 기반이므로 LLVM IR로 쉽게 컴파일 할 수있는 언어를 WebAssembly / asm.js로 변환 할 수 있습니다. 그러나 슬프게도 Python은 Unladen Swallow 와 PyPy의 여러 시도 에 의해 입증 된 것처럼 너무 동적으로 적용 할 수 없습니다 .

이 asm.js 프레젠테이션에는 동적 언어의 상태에 대한 슬라이드가 있습니다 . 이것이 의미하는 바는 현재 전체 VM (C / C ++의 언어 구현)을 WebAssembly / asm.js로 컴파일하고 가능한 경우 JIT로 원본 소스를 해석하는 것만 가능하다는 것입니다. Python의 경우 기존 프로젝트가 여러 개 있습니다.

  1. PyPy : PyPy.js ( PyCon 의 저자 강연 ). 여기에 릴리스 저장소가 있습니다. 기본 JS 파일 pypyjs.vm.js은 13MB (2MB 이후 gzip -6) + Python stdlib + 기타 항목입니다.

  2. CPython : pyodide , EmPython , CPython-Emscripten , EmCPythonempython.js5.8MB ( 이후 2.1MBgzip -6 )이며 stdlib는 없습니다.

  3. Micropython : 이 포크 .

    거기에는 빌드 된 JS 파일이 없었기 때문에 trzeci/emscripten/기성품 인 Emscripten 툴체인 으로 빌드 할 수있었습니다 . 다음과 같은 것 :

     git clone https://github.com/matthewelse/micropython.git
     cd micropython
     docker run --rm -it -v $(pwd):/src trzeci/emscripten bash
     apt-get update && apt-get install -y python3
     cd emscripten
     make -j
     # to run REPL: npm install && nodejs server.js 
    

    그것은 생산 micropython.js1.1 MB (후 2백25킬로바이트의 gzip -d). 후자는 stdlib없이 매우 호환되는 구현 만 필요한 경우 이미 고려할 사항입니다.

    WebAssembly 빌드를 생성하려면 13 행을 다음 Makefile으로 변경할 수 있습니다.

     CC = emcc -s RESERVED_FUNCTION_POINTERS=20 -s WASM=1
    

    그런 다음 다음을 make -j생성합니다.

     113 KB micropython.js
     240 KB micropython.wasm
    

    의 HTML 출력 emcc hello.c -s WASM=1 -o hello.html을보고 이러한 파일을 사용하는 방법을 확인할 수 있습니다.

    이러한 방식으로 WebAssembly에서 PyPy 및 CPython을 잠재적으로 빌드하여 호환 브라우저에서 Python 애플리케이션을 해석 할 수 있습니다.

여기서 흥미로운 또 다른 점은 Python to C ++ 컴파일러 인 Nuitka 입니다. 잠재적으로 Python 앱을 C ++로 빌드 한 다음 Emscripten을 사용하여 CPython과 함께 컴파일 할 수 있습니다. 그러나 실제로 나는 그것을하는 방법을 모릅니다.

솔루션

당분간 수 메가 바이트 크기의 JS 파일을 다운로드 할 수없는 기존 웹 사이트 또는 웹 앱을 구축하는 경우 Python-JavaScript 트랜스 파일러 (예 : Transcrypt ) 또는 JavaScript Python 구현 (예 : Brython)을 살펴보십시오. ). 또는 JavaScript로 컴파일되는 언어 목록 에서 다른 사람들과 함께 행운을 시험해보십시오 .

그렇지 않고 다운로드 크기가 문제가되지 않고 많은 거친 가장자리를 해결할 준비가 되었다면 위의 세 가지 중에서 선택하십시오.

2020 년 3 분기 업데이트

  1. JavaScript 포트 MicroPython 에 통합 되었습니다. 그것은에 살고있는 포트 / 자바 스크립트 .

  2. 이 포트는 MicroPython.js 라는 npm 패키지로 제공됩니다 . RunKit 에서 시험해 볼 수 있습니다 .

  3. Rust에는 RustPython 이라는 적극적으로 개발 된 Python 구현이 있습니다. Rust는 공식적으로 WebAssembly를 컴파일 대상 으로 지원하기 때문에 readme 상단에 데모 링크 가 있다는 것은 놀라운 일이 아닙니다 . 하지만 일찍입니다. 그들의 면책 조항은 다음과 같습니다.

    RustPython은 개발 단계에 있으며 프로덕션 또는 내결함성 설정에서 사용해서는 안됩니다.

    현재 빌드는 Python 구문의 하위 집합 만 지원합니다.


1
이러한 .js 및 .wasm 크기는 실제로 공평하지 않습니다. 스트림 압축이 잘 지원되며 둘 다의 크기를 줄이는 데 사용할 수 있습니다. gzip으로 압축 된 동일한 파일의 크기는 얼마입니까? 그 외에는 좋은 대답입니다.
enigmaticPhysicist

그래서 2020 년에 pyodide가 OP가 찾고있는 가장 가까운 것 같습니다. 웹 어셈블리의 Python 런타임입니다 (C를 넣고 Python을 wasm에 넣는 것으로 가정합니다). 여러 라이브러리도 지원합니다. 또한 사용하기 쉬운 것 같습니다.
David Frick

3

이것은 웹 어셈블리가 가비지 컬렉션을 구현할 때까지 가능하지 않습니다. 여기에서 진행 상황을 확인할 수 있습니다 : https://github.com/WebAssembly/proposals/issues/16


17
반드시 그런 것은 아닙니다. Wasm 위에 GC (특히 Python IIRC에서 사용하는 참조 계수)를 구현할 수 있습니다. 원칙적으로 CPython을 가져와 Emscripten을 사용하여 Wasm으로 컴파일 할 수 있어야합니다.
안드레아스 Rossberg

1
자체 프로젝트처럼 wasm 사운드 위에 GC CPython의 구현 - OP에서 필자는이 도구를 기존 사용하고 싶다고했다
말콤 화이트

3
추가 작업을 수행 할 필요가 없으며 CPython을 컴파일하기 만하면됩니다. 이미 RC 구현 AFAICT가 포함되어 있습니다.
안드레아스 Rossberg

3

간단히 말해서, 트랜스 파일러가 있지만 임의의 Python을 웹 어셈블리로 자동으로 변환 할 수는 없으며 앞으로 오랫동안 가능할 것 같지 않습니다. 이론적으로 언어는 똑같이 강력하고 수동 번역이 항상 가능하지만 Python은 매우 스마트 한 언어 간 컴파일러 (또는 트랜스 파일러)가 필요한 일부 데이터 구조와 표현 모드를 허용합니다 [아래 참조]. 해결 방법은 Python-to-C 기술이 적당히 성숙하기 때문에 Python-C- 웹 어셈블리 일 수 있지만, Python-to-C도 취약하기 때문에 일반적으로 작동하지 않을 것입니다 (아래 참조).

WebAssembly는 http://webassembly.org/docs/high-level-goals/ 에서 볼 수 있듯이 특히 C와 유사한 언어를 대상으로합니다 .

Python에서 C 로의 번역은 PyPy와 같은 도구로 수행 할 수 있습니다. PyPy는 오랫동안 개발 중이지만 여전히 임의의 Python 코드에서는 작동하지 않습니다. 이에 대한 몇 가지 이유가 있습니다.

  1. 파이썬은 매우 편리하고 추상적이며 멋진 데이터 구조를 가지고 있지만 정적 코드로 번역하기는 어렵습니다.
  2. Python은 동적 가비지 수집에 의존합니다.
  3. 대부분의 Python 코드는 다양한 라이브러리에 크게 의존하며, 각 라이브러리에는 고유 한 단점과 문제가 있습니다 (예 : C 또는 어셈블러로 작성).

Python-to-C (또는 Python to C ++)가 왜 그렇게 까다 로웠는지 자세히 살펴보면이 간결한 답변 뒤에있는 자세한 이유를 볼 수 있지만 질문의 범위를 벗어납니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.