Biên dịch Python sang WebAssembly


90

Tôi đã đọc rằng có thể chuyển đổi mã Python 2.7 sang Web Assembly, nhưng tôi không thể tìm thấy hướng dẫn cụ thể về cách làm như vậy.

Cho đến nay, tôi đã biên dịch một chương trình C thành Web Assembly bằng Emscripten và tất cả các thành phần cần thiết của nó, vì vậy tôi biết nó đang hoạt động (hướng dẫn sử dụng: http://webassembly.org/getting-started/developers-guide/ )

Các bước tôi phải thực hiện để thực hiện việc này trên máy Ubuntu là gì? Tôi có phải chuyển đổi mã python thành mã bit LLVM rồi biên dịch nó bằng Emscripten không? Nếu vậy, làm thế nào tôi đạt được điều này?



1
Kiểm tra pyodide: hacks.mozilla.org/2019/04/…
Alex

1
Pyodide đưa thời gian chạy Python vào trình duyệt qua WebAssembly: github.com/iodide-project/pyodide
guettli

Câu trả lời:


146

WebAssembly so với asm.js

Trước tiên, hãy xem xét về nguyên tắc, WebAssembly khác với asm.js như thế nào và liệu có tiềm năng sử dụng lại kiến ​​thức và công cụ hiện có hay không. Sau đây là tổng quan khá tốt:

Hãy tóm tắt lại, WebAssembly (MVP, vì có nhiều hơn trong lộ trình của nó , gần như):

  • là một định dạng nhị phân của AST với kiểu nhập tĩnh, có thể được thực thi bởi các công cụ JavaScript hiện có (và do đó, có thể JIT hoặc AOT được biên dịch),
  • nó nhỏ gọn hơn 10-20% (so sánh được nén) và phân tích thứ tự nhanh hơn JavaScript,
  • nó có thể thể hiện hoạt động cấp thấp hơn không phù hợp với cú pháp JavaScript, đọc asm.js (ví dụ: số nguyên 64 bit, lệnh CPU đặc biệt, SIMD, v.v.)
  • có thể chuyển đổi (ở một mức độ nào đó) sang / từ asm.js.

Do đó, hiện tại WebAssembly là một phiên bản lặp lại trên asm.js và chỉ nhắm mục tiêu C / C ++ (và các ngôn ngữ tương tự).

Python trên web

Có vẻ như GC không phải là thứ duy nhất ngăn mã Python nhắm mục tiêu WebAssembly / asm.js. Cả hai đều đại diện cho mã được nhập tĩnh cấp thấp, trong đó mã Python không thể (thực tế) được. Vì chuỗi công cụ hiện tại của WebAssembly / asm.js dựa trên LLVM, một ngôn ngữ có thể dễ dàng biên dịch sang LLVM IR có thể được chuyển đổi thành WebAssembly / asm.js. Nhưng than ôi, Python quá năng động để phù hợp với nó, như đã được chứng minh bởi Unladen Swallowmột số nỗ lực của PyPy.

Bản trình bày asm.js này có các trang trình bày về trạng thái của các ngôn ngữ động . Điều đó có nghĩa là hiện tại chỉ có thể biên dịch toàn bộ VM (triển khai ngôn ngữ trong C / C ++) sang WebAssembly / asm.js và thông dịch (với JIT nếu có thể) các nguồn gốc. Đối với Python, có một số dự án hiện có:

  1. PyPy: PyPy.js (bài nói của tác giả tại PyCon ). Đây là repo phát hành . Tệp JS chính pypyjs.vm.js, là 13 MB (2MB sau gzip -6) + Python stdlib + các thứ khác.

  2. CPython: pyodide , EmPython , CPython-Emscripten , EmCPython , v.v. empython.jslà 5,8 MB (sau 2,1 MB gzip -6), không có stdlib.

  3. Micropython: ngã ba này .

    Không có tệp JS nào được tạo ở đó, vì vậy tôi đã có thể tạo nó bằng trzeci/emscripten/chuỗi công cụ Emscripten được tạo sẵn. Cái gì đó như:

     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 
    

    Nó tạo ra micropython.js1,1 MB (sau 225 KB gzip -d). Cái sau đã là một cái gì đó cần xem xét, nếu bạn chỉ cần triển khai rất tuân thủ mà không cần stdlib.

    Để sản xuất WebAssembly xây dựng bạn có thể thay đổi dòng 13 của Makefileđể

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

    Sau đó make -jsản xuất:

     113 KB micropython.js
     240 KB micropython.wasm
    

    Bạn có thể xem đầu ra HTML của emcc hello.c -s WASM=1 -o hello.html, để xem cách sử dụng các tệp này.

    Bằng cách này, bạn cũng có thể xây dựng PyPy và CPython trong WebAssembly để diễn giải ứng dụng Python của bạn trong một trình duyệt tuân thủ.

Một điều thú vị khác ở đây là Nuitka , một trình biên dịch từ Python sang C ++. Về khả năng, có thể xây dựng ứng dụng Python của bạn sang C ++ và sau đó biên dịch nó cùng với CPython với Emscripten. Nhưng thực tế tôi không biết phải làm thế nào.

Các giải pháp

Hiện tại, nếu bạn đang xây dựng một trang web hoặc ứng dụng web thông thường trong đó tải xuống tệp JS vài megabyte hầu như không phải là một tùy chọn, hãy xem các bộ chuyển đổi Python-sang-JavaScript (ví dụ: Transcrypt ) hoặc triển khai JavaScript Python (ví dụ: Brython ). Hoặc thử vận ​​may của bạn với những người khác từ danh sách các ngôn ngữ biên dịch sang JavaScript .

Nếu không, nếu kích thước tải xuống không phải là vấn đề và bạn đã sẵn sàng giải quyết nhiều cạnh thô, hãy chọn giữa ba điều trên.

Cập nhật Q3 2020

  1. Cổng JavaScript đã được tích hợp vào MicroPython. Nó sống trong các cổng / javascript .

  2. Cổng có sẵn dưới dạng gói npm được gọi là MicroPython.js . Bạn có thể dùng thử trong RunKit .

  3. Có một triển khai Python được phát triển tích cực trong Rust, được gọi là RustPython . Vì Rust chính thức hỗ trợ WebAssembly dưới dạng mục tiêu biên dịch , nên không có gì ngạc nhiên khi có liên kết demo ngay trên đầu readme. Tuy nhiên, vẫn còn sớm. Tuyên bố từ chối trách nhiệm của họ sau đây.

    RustPython đang trong giai đoạn phát triển và không được sử dụng trong sản xuất hoặc cài đặt không dung nạp lỗi.

    Bản dựng hiện tại của chúng tôi chỉ hỗ trợ một tập hợp con cú pháp Python.


1
Các kích thước .js và .wasm đó không thực sự công bằng. Nén luồng được hỗ trợ tốt và có thể được sử dụng để giảm kích thước của cả hai. Kích thước của các tệp giống nhau, được nén như thế nào? Ngoài ra, câu trả lời tốt.
enigmaticPhysicist

Vì vậy, muốn nói thêm rằng vào năm 2020, có vẻ như pyodide là thứ gần nhất mà OP đang tìm kiếm. Đó là thời gian chạy Python trong web assembly (tôi sẽ giả sử đặt C và sau đó Python thành wasm). Nó cũng hỗ trợ nhiều thư viện. Ngoài ra, có vẻ đủ dễ sử dụng.
David Frick

3

Điều này sẽ không thể thực hiện được cho đến khi web assembly thực hiện thu gom rác. Bạn có thể theo dõi tiến trình tại đây: https://github.com/WebAssembly/propestions/issues/16


17
Không cần thiết. Bạn có thể triển khai GC - và đặc biệt là đếm tham chiếu, vì nó được Python IIRC sử dụng - trên Wasm. Về nguyên tắc, bạn sẽ có thể sử dụng CPython và biên dịch nó thành Wasm bằng Emscripten.
Andreas Rossberg

1
Mất của tôi từ OP là họ muốn sử dụng công cụ hiện có - thực hiện CPython GC trên đầu trang của âm thanh wasm như một dự án của riêng mình
Malcolm trắng

3
Bạn không cần phải làm gì thêm, chỉ cần tải CPython để biên dịch. Nó đã chứa phần triển khai RC, AFAICT.
Andreas Rossberg

3

Tóm lại: Có những bộ chuyển đổi, nhưng bạn không thể tự động chuyển đổi bất kỳ Python tùy ý nào sang Web Assembly, và tôi nghi ngờ bạn sẽ có thể làm được điều này trong một thời gian dài sắp tới. Mặc dù về mặt lý thuyết, các ngôn ngữ đều mạnh mẽ như nhau và luôn có thể dịch thủ công, nhưng Python cho phép một số cấu trúc dữ liệu và chế độ diễn đạt yêu cầu trình biên dịch liên ngôn ngữ (hoặc trình chuyển tiếp) rất thông minh [xem bên dưới]. Một giải pháp thay thế có thể là Python sang C thành Web Assembly vì công nghệ python-to-C đã hoàn thiện ở mức độ vừa phải, nhưng điều đó thường không hoạt động vì Python-to-C cũng rất mỏng manh (xem bên dưới).

WebAssembly được nhắm mục tiêu cụ thể đến các ngôn ngữ giống C như bạn có thể thấy tại http://webassembly.org/docs/high-level-goals/

Việc dịch từ Python sang C có thể được thực hiện bằng các công cụ như PyPy, đã được phát triển trong một thời gian dài, nhưng vẫn không hoạt động đối với mã Python tùy ý. Cái này có một vài nguyên nhân:

  1. Python có một số cấu trúc dữ liệu rất tiện dụng, trừu tượng và đẹp mắt, nhưng chúng rất khó để dịch thành mã tĩnh.
  2. Python phụ thuộc vào việc thu thập rác động.
  3. Hầu hết mã Python phụ thuộc rất nhiều vào các thư viện khác nhau, mỗi thư viện đều có những vấn đề và điều khó hiểu riêng (chẳng hạn như được viết bằng C, hoặc thậm chí là trình hợp dịch).

Nếu bạn xem xét kỹ hơn lý do tại sao Python-to-C (hoặc Python sang C ++) lại phức tạp đến vậy, bạn có thể thấy lý do chi tiết đằng sau câu trả lời ngắn gọn này, nhưng tôi nghĩ điều đó nằm ngoài phạm vi câu hỏi của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.