Pythonmonkey เป็นเครื่องยนต์ JavaScript Mozilla Spidermonkey ที่ฝังอยู่ในรันไทม์ Python โดยใช้เครื่องยนต์ Python เพื่อให้สภาพแวดล้อมโฮสต์ JavaScript
เรามีอาร์เรย์ JavaScript และวิธีการวัตถุที่ใช้ในรายการ Python และพจนานุกรมโดยใช้ CPython C API และค่าผกผันโดยใช้ Mozilla Firefox Spidermonkey JavaScript C ++ API
โครงการนี้มาถึง MVP ณ เดือนกันยายน 2567 มันอยู่ภายใต้การบำรุงรักษาโดยการกระจาย
การมีส่วนร่วมและข้อเสนอแนะจากภายนอกยินดีต้อนรับและสนับสนุน
$ pip install pythonmonkey from pythonmonkey import eval as js_eval
js_eval ( "console.log" )( 'hello, world' )eval() ใน Python ซึ่งยอมรับรหัส JS และส่งคืน JS-> Python Coerced Valesrequire ฟังก์ชั่นส่งคืน dict ที่ถูกบีบบังคับของการส่งออกโมดูลอ่านสิ่งนี้หากคุณต้องการสร้างเวอร์ชันท้องถิ่น
คุณจะต้องติดตั้งต่อไปนี้ (ซึ่งสามารถทำได้โดยอัตโนมัติโดยเรียกใช้ ./setup.sh ):
รัน poetry install คำสั่งนี้จะรวบรวมโครงการโดยอัตโนมัติและติดตั้งโครงการเช่นเดียวกับการพึ่งพาในบทกวี VirtualEnv หากคุณต้องการสร้างเอกสารให้ตั้งค่าตัวแปรสภาพแวดล้อม BUILD_DOCS เช่น So: BUILD_DOCS=1 poetry install Pythonmonkey รองรับการสร้างหลายประเภทซึ่งคุณสามารถสร้างได้โดยการตั้งค่าตัวแปรสภาพแวดล้อม BUILD_TYPE เช่น SO: BUILD_TYPE=Debug poetry install ประเภทการสร้างคือ (ตัวพิมพ์ใหญ่):
Release : สัญลักษณ์ที่ถูกถอดออกการเพิ่มประสิทธิภาพสูงสุด (ค่าเริ่มต้น)DRelease : เหมือนกับ Release ยกเว้นสัญลักษณ์จะไม่ถูกถอดออกDebug : การเพิ่มประสิทธิภาพขั้นต่ำSanitize : เช่นเดียวกับ Debug ยกเว้นเมื่อเปิดใช้งาน addresssanitizerProfile : เช่นเดียวกับ Debug ยกเว้นเปิดใช้งานการทำโปรไฟล์None : อย่ารวบรวม (มีประโยชน์ถ้าคุณต้องการสร้างเอกสารเท่านั้น) หากคุณใช้ VSCODE คุณสามารถกด Ctrl + Shift + B เพื่อเรียกใช้งานสร้าง - เรามีไฟล์ tasks.json ที่กำหนดค่าไว้สำหรับคุณ
poetry install --no-root --only=devpoetry run pytest ./tests/pythonpoetry run bash ./peter-jr ./tests/js/สำหรับผู้ใช้ VSCODE คล้ายกับงานสร้างเรามีงานทดสอบพร้อมใช้งาน
จำเป็นต้องใช้ NPM (node.js) ในระหว่างการติดตั้ง เพื่อเติมการพึ่งพา JS
$ pip install pythonmonkey$ pip install --extra-index-url https://nightly.pythonmonkey.io/ --pre pythonmonkey pythonmonkey มีอยู่ในบทกวี VirtualEnv เมื่อคุณรวบรวมโครงการโดยใช้บทกวี
$ poetry run python Python 3.10 .6 ( main , Nov 14 2022 , 16 : 10 : 14 ) [ GCC 11.3 .0 ] on linux
Type "help" , "copyright" , "credits" or "license" for more information .
> >> import pythonmonkey as pm
>> > hello = pm . eval ( "() => {return 'Hello from Spidermonkey!'}" )
>> > hello ()
'Hello from Spidermonkey!'หรือคุณสามารถสร้างแพ็คเกจที่ติดตั้งได้โดยเรียกใช้
$ cd python/pminit && poetry build --format=sdist && cd - && mv -v python/pminit/dist/ * ./dist/
$ poetry build --format=wheel และติดตั้งโดย pip install ./dist/*
การติดตั้ง pythonmonkey จะติดตั้งแพ็คเกจ pminit เป็นการพึ่งพา อย่างไรก็ตาม pip uninstall แพ็คเกจจะไม่ลบการพึ่งพาโดยอัตโนมัติ
หากคุณต้องการลบ pythonmonkey ออกจากระบบของคุณอย่างหมดจดให้ทำสิ่งต่อไปนี้:
$ pip uninstall pythonmonkey pminitpoetry run gdb python ดู Python Wiki: debuggingwithgdb หากคุณใช้ VSCODE มันจะสะดวกกว่าในการดีบักในดีบั๊กในตัวของ VSCODE เพียงกด F5 บนไฟล์ Python ที่เปิดอยู่ในตัวแก้ไขเพื่อเริ่มการดีบัก - เรามีไฟล์ launch.json ที่กำหนดค่าสำหรับคุณ
วิธีการเหล่านี้จะถูกส่งออกจากโมดูล Pythonmonkey ดูคำจำกัดความใน Python/Pythonmonkey/Pythonmonkey.pyi
ประเมินรหัส JavaScript ความหมายของการประเมินนี้คล้ายกับการประเมินที่ใช้ใน JavaScript; นิพจน์ล่าสุดที่ประเมินในสตริง code ใช้เป็นค่าส่งคืนของฟังก์ชันนี้ ในการประเมิน code ในโหมดที่เข้มงวดนิพจน์แรกควรเป็นสตริง "use strict"
ฟังก์ชั่นการประเมินสนับสนุนวัตถุตัวเลือกที่อาจส่งผลต่อวิธีการประเมินรหัส JS ในรูปแบบที่มีประสิทธิภาพ พวกเขาส่วนใหญ่ขึ้นอยู่กับ CompileOptions ของ Spidermonkey ปุ่มตัวเลือกที่รองรับคือ:
filename : ตั้งชื่อไฟล์ของรหัสนี้เพื่อวัตถุประสงค์ในการสร้างร่องรอยสแต็ก ฯลฯlineno : ตั้งค่าหมายเลขบรรทัดของรหัสนี้เพื่อวัตถุประสงค์ในการสร้างร่องรอยสแต็ก ฯลฯcolumn : ตั้งค่าคอลัมน์หมายเลขออฟเซ็ตของรหัสนี้เพื่อวัตถุประสงค์ในการสร้างร่องรอยสแต็ก ฯลฯmutedErrors : หากตั้งค่าเป็น True ข้อผิดพลาดของการประเมินหรือการปฏิเสธที่ไม่มีการจัดการจะถูกละเว้น ("ปิดเสียง") ค่าเริ่ม FalsenoScriptRval : ถ้า False ให้ส่งคืนค่านิพจน์สุดท้ายของสคริปต์เป็นค่าผลลัพธ์ไปยังผู้โทร ค่าเริ่ม FalseselfHosting : ทดลองstrict : ประเมินการประเมินในโหมดที่เข้มงวด ( "use strict" ) ค่าเริ่ม Falsemodule : ระบุว่าไฟล์เป็นโมดูล ECMASCRIPT (รหัสโหมดที่เข้มงวดเสมอและไม่อนุญาตความคิดเห็น HTML) ค่าเริ่ม FalsefromPythonFrame : สร้างชื่อเทียบเท่าชื่อไฟล์ลินินและคอลัมน์ตามตำแหน่งของการเรียก Python ไปยัง Eval สิ่งนี้ทำให้สามารถประเมินตัวอักษรสตริง Multiline Python และสร้างร่องรอยสแต็กใน JS ชี้ไปที่ข้อผิดพลาดในไฟล์ต้นฉบับ Python undefined ใน JavaScript; หากคุณต้องการส่งคืนฟังก์ชั่นคุณต้องประเมินนิพจน์: pythonmonkey . eval ( "myFunction() { return 123 }; myFunction" ) pythonmonkey . eval ( "(myFunction() { return 123 })" ) pythonmonkey . eval ( "(thing) => console.log('you said', thing)" )( "this string came from Python" ) ส่งคืนการส่งออกของโมดูล CommonJS ที่ระบุโดย moduleIdentifier โดยใช้ความหมายแบบ CommonJS มาตรฐาน
require.js - โมดูล JavaScript; ซอร์สโค้ดตกแต่งวัตถุ exports.py - โมดูล Python; ซอร์สโค้ดตกแต่ง exports dict.json - โมดูล JSON; การส่งออกเป็นผลมาจากการแยกวิเคราะห์ข้อความ JSON ในไฟล์Python dict ซึ่งเทียบเท่ากับวัตถุ Global This ใน JavaScript
ฟังก์ชั่นโรงงานที่ส่งคืนฟังก์ชันใหม่
โหลดและประเมินโมดูลโปรแกรม (หลัก) โมดูลโปรแกรมจะต้องเขียนใน JavaScript โมดูลโปรแกรมไม่จำเป็นเว้นแต่จะมีจุดเริ่มต้นหลักของโปรแกรมของคุณใน JavaScript
ควรใช้ความระมัดระวังเพื่อให้แน่ใจว่ามีเพียงโมดูลโปรแกรมเดียวเท่านั้นที่เรียกใช้ต่อบริบท JS
ตรวจสอบ code สตริงและส่งคืนเท็จหากสตริงอาจกลายเป็นคำสั่ง JS ที่ถูกต้องด้วยการเพิ่มบรรทัดเพิ่มเติม สิ่งนี้ถูกใช้ภายในโดย PMJs และมีประโยชน์มากสำหรับการสร้าง JavaScript Repls; ความคิดคือการสะสมบรรทัดในบัฟเฟอร์จนกว่า iscompileableunit จะเป็นจริงจากนั้นประเมินบัฟเฟอร์ทั้งหมด
ส่งคืนฟังก์ชั่น Python ซึ่งเรียกใช้ function ด้วย JS New Operator
import pythonmonkey as pm
> >> pm . eval ( "class MyClass { constructor() { console.log('ran ctor') }}" )
> >> MyClass = pm . eval ( "MyClass" )
> >> MyClass ()
Traceback ( most recent call last ):
File "<stdin>" , line 1 , in < module >
pythonmonkey . SpiderMonkeyError : TypeError : class constructors must be invoked with 'new'
>> > MyClassCtor = pm . new ( MyClass )
>> > MyClassCtor ()
ran ctor
{}
>> > นี่คือตัวดำเนินการ JS typeof ที่ห่อหุ้มด้วยฟังก์ชั่นเพื่อให้สามารถใช้งานได้ง่ายจาก Python
คลาสมาตรฐาน JS ทั้งหมด (อาร์เรย์, ฟังก์ชั่น, วัตถุ, วันที่ ... ) และวัตถุ (Globalthis, FinalizationRegistry ... ) มีให้บริการเป็นการส่งออกของโมดูล Pythonmonkey การส่งออกเหล่านี้สร้างขึ้นโดยการแจกแจงตัวแปรทั่วโลกในบริบท Spidermonkey ปัจจุบัน รายการปัจจุบันคือ:
undefined, boolean, json, วันที่, คณิตศาสตร์, จำนวน, สตริง, regexp, ข้อผิดพลาด, InternalError, AggregateRror, EvalerRor, Rangeerror, ReferenceError, SyntaxError, TypeError, Urierror, Arraybuffer, Int8Array, Uint8array, Int166Array float64array, uint8clampedarray, bigint64array, biguint64array, bigint, พร็อกซี, beakmap, แผนที่, ชุด, dataView, สัญลักษณ์, intl, สะท้อน, ความอ่อนแอ, คำสัญญา, webassembly, beakref, iterator, asynciterator, nan encodeuri, decodeuricomponent, encodeuricomponent, ฟังก์ชั่น, วัตถุ, debuggerglobal, finalizationRegistry, อาร์เรย์, globalthis
ดูคำจำกัดความใน Python/Pythonmonkey/Global.D.TS รวมทั้ง:
consoleatobbtoasetTimeoutclearTimeout ระบบย่อย CommonJS เปิดใช้งานโดยการเรียกใช้ require หรือส่งออก createRequire ของโมดูล Pythonmonkey (Python)
requireexportsmodule__filename__dirnamepython.print - ฟังก์ชั่นการพิมพ์ Pythonpython.getenv - ฟังก์ชัน Python getenvpython.stdout - วัตถุที่มีวิธี read และ write ซึ่งอ่านและเขียนถึง stdoutpython.stderr - วัตถุที่มีวิธี read และ write ซึ่งอ่านและเขียนถึง stderrpython.exec - ฟังก์ชัน Python Execpython.eval - ฟังก์ชัน Python Evalpython.exit - ออกผ่าน sys.exit (); รหัสออกคืออาร์กิวเมนต์ฟังก์ชันหรือ python.exit.codepython.paths - รายการ Python sys.paths ที่มองเห็นได้ใน JS เป็นอาร์เรย์ เมื่อส่งตัวแปรจาก Python ไปยัง JavaScript Pythonmonkey จะบีบบังคับหรือห่อตัวแปรอย่างชาญฉลาดตามประเภทของพวกเขา Pythonmonkey จะแบ่งปันร้านค้าสำรอง (ใช้หน่วยความจำเดียวกัน) สำหรับ ctypes, อาร์เรย์พิมพ์และสตริง; การย้ายประเภทเหล่านี้ข้ามอุปสรรคภาษานั้นเร็วมากเพราะไม่มีการคัดลอกเกี่ยวข้อง
หมายเหตุ: มีแผนใน Python 3.12 (PEP 623) เพื่อเปลี่ยนการแสดงสตริงภายในเพื่อให้อักขระทุกตัวในสตริงใช้หน่วยความจำสี่ไบต์ สิ่งนี้จะทำลายการถ่ายโอนสตริงที่รวดเร็วสำหรับ Pythonmonkey เนื่องจากต้องอาศัยเค้าโครงหน่วยความจำเหมือนกันใน Python และ JavaScript จากการเขียนนี้ (กรกฎาคม 2023), สตริง Python "คลาสสิก" ยังคงทำงานในรุ่นเบต้า 3.12
ในกรณีที่ไม่สามารถใช้การสนับสนุนที่ใช้ร่วมกันได้ Pythonmonkey จะปล่อย wrappers โดยอัตโนมัติที่ใช้โครงสร้างข้อมูล "ของจริง" เป็นอำนาจที่มีค่า มีการคัดลอกเฉพาะภายในที่ไม่เปลี่ยนรูป ซึ่งหมายความว่าหากคุณอัปเดตวัตถุใน JavaScript คำสั่งที่เกี่ยวข้องใน Python จะได้รับการปรับปรุง ฯลฯ
อาร์เรย์ JavaScript และวิธีการวัตถุถูกนำไปใช้ในรายการ Python และพจนานุกรมและในทางกลับกัน
| ประเภทงูหลาม | ประเภท JavaScript |
|---|---|
| สาย | สาย |
| จำนวนเต็ม | ตัวเลข |
| บูล | บูลีน |
| การทำงาน | การทำงาน |
| คำสั่ง | วัตถุ |
| รายการ | อาร์เรย์ |
| วันที่ | วัตถุวันที่ |
| รอคอยได้ | สัญญา |
| ข้อผิดพลาด | วัตถุข้อผิดพลาด |
| บัฟเฟอร์ | อาร์เรย์บัฟเฟอร์ |
| ประเภท JavaScript | ประเภทงูหลาม |
|---|---|
| สาย | pythonmonkey.jsstringproxy (สตริง) |
| ตัวเลข | ลอย |
| Bigint | Pythonmonkey.bigint (จำนวนเต็ม) |
| บูลีน | บูล |
| การทำงาน | pythonmonkey.jsfunctionproxy |
| วัตถุ - ส่วนใหญ่ | pythonmonkey.jsobjectproxy (dict) |
| วัตถุ - วันที่ | วันที่ |
| วัตถุ - อาร์เรย์ | pythonmonkey.jsarrayproxy (รายการ) |
| วัตถุ - สัญญา | รอคอยได้ |
| วัตถุ - ArrayBuffer | บัฟเฟอร์ |
| วัตถุ - พิมพ์อาร์เรย์ | บัฟเฟอร์ |
| วัตถุ - ข้อผิดพลาด | ข้อผิดพลาด |
คุณสามารถบังคับให้ตัวเลขใน JavaScript ถูกบีบบังคับเป็นจำนวนเต็มโดยการคัดเลือกให้ Bigint:
function myFunction ( a , b ) {
const result = calculate ( a , b ) ;
return BigInt ( Math . floor ( result ) ) ;
} pythonmonkey.bigint Object ทำงานเหมือน int ใน Python แต่มันจะถูกบังคับให้เป็น Bigint ใน JavaScript:
import pythonmonkey
def fn myFunction ()
result = 5
return pythonmonkey . bigint ( result )คุณสามารถใช้ JavaScript IIFE เพื่อสร้างขอบเขตที่คุณสามารถฉีดสัญลักษณ์ Python:
globalThis . python . exit = pm . eval ( """'use strict';
(exit) => function pythonExitWrapper(exitCode) {
if (typeof exitCode === 'number')
exitCode = BigInt(Math.floor(exitCode));
exit(exitCode);
}
""" )( sys . exit ); คุณต้องใช้วงจรกิจกรรมเพื่อใช้ setTimeout และ Promise <=> การบีบบังคับ awaitable
import asyncio
async def async_fn ():
await pm . eval ( """
new Promise((resolve) => setTimeout((...args) => {
console.log(args);
resolve();
}, 1000, 42, "abc")
)
""" )
await pm . eval ( "async (x) => await x" )( asyncio . sleep ( 0.5 ))
asyncio . run ( async_fn ()) เชลล์ JavaScript พื้นฐาน, pmjs , เรือที่มี Pythonmonkey เชลล์นี้สามารถทำหน้าที่เป็นโปรแกรม REPL หรือเรียกใช้ JavaScript; มันมีแนวคิดคล้ายกับเชลล์ node ซึ่งจัดส่งด้วยโหนด
PMJS เริ่มระบบย่อย CommonJS ของ Pythonmonkey ซึ่งอนุญาตให้ใช้โมดูล CommonJS ที่มีความหมายที่คล้ายกับ node.js - เช่นโมดูลการค้นหา. paths, เข้าใจแพ็คเกจ. json, index.js และอื่น ๆ ดูโมดูล CTX สำหรับรายการคุณสมบัติที่รองรับทั้งหมด
นอกเหนือจากโมดูล CommonJS ที่เขียนใน JavaScript แล้ว Pythonmonkey ยังรองรับโมดูล CommonJS ที่เขียนใน Python เพียงตกแต่งคำสั่งชื่อ exports ภายในไฟล์ที่มีส่วนขยาย .py และสามารถโหลดได้โดย require() - ใน JavaScript หรือ Python
โมดูลโปรแกรมหรือโมดูลหลักเป็นโมดูลพิเศษใน CommonJS ในโมดูลโปรแกรม:
globalThisarguments ในอาร์เรย์ที่ถือเวกเตอร์อาร์กิวเมนต์ของโปรแกรม (อาร์กิวเมนต์บรรทัดคำสั่ง) $ echo " console.log('hello world') " > my-program.js
$ pmjs my-program.js
hello world
$ // date-lib.js - require("./date-lib")
const d = new Date ( ) ;
exports . today = ` ${ d . getFullYear ( ) } - ${ String ( d . getMonth ( ) ) . padStart ( 2 , '0' ) } - ${ String ( d . getDay ( ) ) . padStart ( 2 , '0' ) } ` # date-lib.py - require("./date-lib")
from datetime import date # You can use Python libraries.
exports [ 'today' ] = date . today () หากคุณมีปัญหากับฟังก์ชั่น CommonJs ให้ตั้งค่าสภาพแวดล้อมตัวแปร DEBUG='ctx-module*' และคุณสามารถเห็นชื่อไฟล์ที่พยายามโหลด
Pythonmonkey มีตัวดีบั๊กบรรทัดคำสั่ง JavaScript-Line ที่เรียกว่า PMDB ซึ่งจะถูกเรียกใช้โดยอัตโนมัติบน debugger; ข้อความและข้อยกเว้นที่ไม่ถูกต้อง
หากต้องการเปิดใช้งาน PMDB เพียงโทร from pythonmonkey.lib import pmdb; pmdb.enable() ก่อนทำอะไรใน Pythonmonkey
import pythonmonkey as pm
from pythonmonkey . lib import pmdb
pmdb . enable ()
pm . eval ( "..." ) เรียกใช้คำสั่ง help ใน PMDB เพื่อดูคำสั่งที่มีอยู่
(pmdb) > help
List of commands:
• ...
• ... .help ในการแก้ไข--help--inspect เปิดใช้งาน PMDB ซึ่งเป็นตัวดีบักบรรทัดคำสั่ง JavaScript ที่เหมือน GDB-r สามารถใช้ในการโหลดโมดูลก่อนโปรแกรมของคุณหรือการเรียกใช้ RUNS-e สามารถใช้ประเมินรหัส -เช่นกำหนดตัวแปรทั่วโลก -ก่อนโปรแกรมของคุณหรือการทำงานใหม่$1 , $2 ฯลฯ $ pmjs
Welcome to PythonMonkey v1.0.0.
Type ".help" for more information.
> .python import sys
> .python sys.path
$1 = { '0': '/home/wes/git/pythonmonkey2',
'1': '/usr/lib/python310.zip',
'2': '/usr/lib/python3.10',
'3': '/usr/lib/python3.10/lib-dynload',
'4': '/home/wes/.cache/pypoetry/virtualenvs/pythonmonkey-StuBmUri-py3.10/lib/python3.10/site-packages',
'5': '/home/wes/git/pythonmonkey2/python' }
> $1 [3]
'/usr/lib/python3.10/lib-dynload'
>