Pythonmonkey هو محرك Mozilla Spidermonkey JavaScript مضمن في وقت تشغيل Python ، باستخدام محرك Python لتوفير بيئة مضيف JavaScript.
نحن نعرض أساليب مجموعة JavaScript والكائنات التي تم تنفيذها على قائمة Python والقواميس باستخدام Cpython C API ، والعكس باستخدام Mozilla Firefox Spidermonkey JavaScript C ++ API.
وصل هذا المشروع إلى MVP اعتبارًا من سبتمبر 2024. إنه قيد الصيانة عن طريق التوزيع.
المساهمات الخارجية والتعليقات موضع ترحيب وتشجيع.
$ pip install pythonmonkey from pythonmonkey import eval as js_eval
js_eval ( "console.log" )( 'hello, world' )eval()require وظيفة ، وإرجاع dict قسرية من صادرات الوحدة النمطيةاقرأ هذا إذا كنت ترغب في إنشاء نسخة محلية.
ستحتاج إلى التثبيت التالي (والذي يمكن القيام به تلقائيًا عن طريق التشغيل ./setup.sh ):
تشغيل poetry install . يقوم هذا الأمر تلقائيًا بتجميع المشروع وتثبيت المشروع وكذلك التبعيات في Poetry VirtualEnv. إذا كنت ترغب في إنشاء مستندات ، فقم بتعيين متغير BUILD_DOCS Environment ، مثل SO: BUILD_DOCS=1 poetry install . يدعم Pythonmonkey أنواعًا متعددة للبناء ، والتي يمكنك إنشاءها عن طريق تعيين متغير بيئة BUILD_TYPE ، مثل SO: BUILD_TYPE=Debug poetry install . أنواع البناء هي (غير حساسة للحالة):
Release : الرموز المجردة ، والتحسينات القصوى (الافتراضي)DRelease : نفس Release ، باستثناء الرموز لا يتم تجريدهاDebug : الحد الأدنى من التحسيناتSanitize : مثل Debug ، إلا مع تمكين OdventsanitizerProfile : مثل 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 في Poetry 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. تشبه دلالات هذه التقييم إلى حد كبير التقييم المستخدمة في جافا سكريبت. يتم استخدام التعبير الأخير الذي تم تقييمه في سلسلة code كقيمة إرجاع هذه الوظيفة. لتقييم code في الوضع الصارم ، يجب أن يكون التعبير الأول هو السلسلة "use strict" .
تدعم دالة eval كائن خيارات يمكن أن يؤثر على كيفية تقييم رمز JS بطرق قوية. وهي تعتمد إلى حد كبير على CompileOptions SpidermonKey. مفاتيح الخيار المدعوم هي:
filename : اضبط اسم ملف هذا الرمز لأغراض إنشاء آثار المكدس وما إلى ذلك.lineno : قم بتعيين إزاحة رقم السطر لهذا الرمز لأغراض توليد آثار المكدس وما إلى ذلك.column : اضبط إزاحة رقم العمود لهذا الرمز لأغراض توليد آثار المكدس وما إلى ذلك.mutedErrors : إذا تم ضبطها على True ، يتم تجاهل أخطاء eval أو الرفض غير المعلوم ("صامت"). الافتراضي False .noScriptRval : إذا كان False ، فأرجع قيمة التعبير الأخيرة للنص كقيمة النتيجة للمتصل. الافتراضي False .selfHosting : التجريبيةstrict : تقييم قسري في الوضع الصارم ( "use strict" ). الافتراضي False .module : تشير إلى أن الملف هو وحدة ECMASCRIPT (دائمًا رمز الوضع الصارم وعدم السماح بتعليقات HTML). الافتراضي False .fromPythonFrame : قم بإنشاء ما يعادل اسم الملف ، والكتانو ، والعمود بناءً على موقع مكالمة Python إلى Eval. هذا يجعل من الممكن تقييم Python Multiiline String Distalals وإنشاء آثار المكدس في JS تشير إلى الخطأ في ملف Python Source. 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 - وحدة بيثون ؛ رمز المصدر يزين exports.json - JSON MODUULE ؛ الصادرات هي نتيجة تحليل نص JSON في الملفقول بيثون الذي يعادل الكائن العالمي في جافا سكريبت.
وظيفة المصنع التي تُرجع وظيفة جديدة تتطلب
تحميل وتقييم وحدة البرنامج (الرئيسية). يجب كتابة وحدات البرنامج في JavaScript. وحدات البرنامج ليست ضرورية ما لم تتم كتابة نقطة الدخول الرئيسية لبرنامجك في JavaScript.
يجب توخي الحذر لضمان تشغيل وحدة برنامج واحد فقط لكل سياق JS.
يفحص code السلسلة ويُرجع خطأ إذا كانت السلسلة قد تصبح عبارة JS صالحة مع إضافة المزيد من الخطوط. يتم استخدام هذا داخليًا من قِبل PMJs ويمكن أن يكون مفيدًا للغاية لبناء javaScript Repls ؛ تتمثل الفكرة في تجميع الخطوط في المخزن المؤقت حتى يكون IsCompilableUnit صحيحًا ، ثم تقييم المخزن المؤقت بالكامل.
إرجاع وظيفة Python التي تستدعي function مع مشغل JS الجديد.
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
{}
>> > هذا هو مشغل typeof JS ، ملفوف في وظيفة بحيث يمكن استخدامه بسهولة من Python.
جميع فئات JS القياسية (الصفيف ، الوظيفة ، الكائن ، التاريخ ...) والكائنات (GlobalThis ، FinivingRegistry ...) متوفرة كصادرات لوحدة Pythonmonkey. يتم إنشاء هذه الصادرات عن طريق تعداد المتغير العالمي في سياق SpidermonKey الحالي. القائمة الحالية هي:
غير محدد ، منطقية ، JSON ، التاريخ ، الرياضيات ، الرقم ، السلسلة ، regexp ، خطأ ، internalerror ، assregateerror ، evalerror ، rangeerror ، referenceerror ، syntaxerror ، typeerror ، urierror ، arraybuffer ، int8array ، uint8array ، int16array ، uint16array ، float64array ، uint8clampedarray ، bigint64array ، biguint64array ، bigint ، الوكيل ، الضعف ، الخريطة ، مجموعة ، dataview ، الرمز ، intl ، التفكير ، الضعف ، الوعد ، webassembl Encodeuri ، decodeuricomponent ، encodeuricomponment ، وظيفة ، كائن ، مصحح DebuggerGlobal ، اللمسات الأخيرة
انظر التعاريف في 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.code .python.paths - قائمة Python Sys.paths ، مرئية في JS كصفيف عند إرسال متغيرات من Python إلى JavaScript ، سيشجع Pythonmonkey بذكاء أو يلف متغيراتك بناءً على نوعها. سيشارك Pythonmonkey متاجر الدعم (استخدم نفس الذاكرة) لأنواع Ctypes ، والصفائف المكتوبة ، والسلاسل ؛ إن نقل هذه الأنواع عبر حاجز اللغة سريع للغاية لأنه لا يوجد نسخ متورط.
ملاحظة: هناك خطط في Python 3.12 (PEP 623) لتغيير تمثيل السلسلة الداخلية بحيث يستخدم كل حرف في السلسلة أربعة بايت من الذاكرة. سيؤدي ذلك إلى كسر عمليات نقل السلسلة السريعة لـ Pythonmonkey ، حيث يعتمد على تخطيط الذاكرة كما هو الحال في Python و JavaScript. اعتبارًا من كتابة هذه السطور (يوليو 2023) ، لا تزال سلاسل بيثون "الكلاسيكية" تعمل في الإصدار التجريبي 3.12.
عندما لا يكون متجر الدعم المشترك ممكنًا ، سيقوم Pythonmonkey تلقائيًا بتصميم الأغطية التي تستخدم بنية البيانات "الحقيقية" كسلطة قيمتها. يتم نسخ الوادلات غير القابلة للتغيير فقط. هذا يعني أنه إذا قمت بتحديث كائن في JavaScript ، فسيتم تحديث التصميم المقابل في Python ، إلخ.
يتم تنفيذ أساليب مجموعة JavaScript وطرق الكائن في قائمة Python والقواميس ، والعكس بالعكس.
| نوع بيثون | نوع JavaScript |
|---|---|
| خيط | خيط |
| عدد صحيح | رقم |
| بول | منطقية |
| وظيفة | وظيفة |
| التقليل | هدف |
| قائمة | صفيف |
| DateTime | كائن التاريخ |
| في انتظار | يعد |
| خطأ | كائن الخطأ |
| المخزن المؤقت | arraybuffer |
| نوع JavaScript | نوع بيثون |
|---|---|
| خيط | pythonmonkey.jsstringproxy (سلسلة) |
| رقم | يطفو |
| Bigint | pythonmonkey.bigint (عدد صحيح) |
| منطقية | بول |
| وظيفة | Pythonmonkey.jsfunctionproxy |
| كائن - معظم | pythonmonkey.jsobjectproxy (DICT) |
| كائن - التاريخ | DateTime |
| كائن - صفيف | pythonmonkey.jsarrayproxy (قائمة) |
| كائن - وعد | في انتظار |
| كائن - ArrayBuffer | المخزن المؤقت |
| كائن - اكتب المصفوفات | المخزن المؤقت |
| كائن - خطأ | خطأ |
يمكنك فرض رقم في JavaScript على إكراه كصاحب صحيح عن طريق إلقاءه على Bigint:
function myFunction ( a , b ) {
const result = calculate ( a , b ) ;
return BigInt ( Math . floor ( result ) ) ;
} يعمل كائن pythonmonkey.bigint مثل int في Python ، ولكن سيتم إجباره على أنه Bigint في JavaScript:
import pythonmonkey
def fn myFunction ()
result = 5
return pythonmonkey . bigint ( result )يمكنك استخدام JavaScript iife لإنشاء نطاق يمكنك من خلاله حقن رموز الثعبان:
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 التي تشحن مع node.js.
PMJS يبدأ النظام الفرعي لـ Pythonmonkey من Pythonmonkey ، والذي يسمح له باستخدام وحدات CommonJS ، مع دلالات تشبه node.js - على سبيل المثال الوحدة النمطية. راجع وحدة CTX للحصول على قائمة كاملة بالميزات المدعومة.
بالإضافة إلى وحدات CommonJS المكتوبة في JavaScript ، يدعم Pythonmonkey وحدات CommonJS المكتوبة في Python. ما عليك سوى تزيين exports المسمى DICT داخل ملف بامتداد .py ، ويمكن تحميله بواسطة require() - في JavaScript أو Python.
وحدة البرنامج ، أو الوحدة الرئيسية ، هي وحدة خاصة في الشائعة. في وحدة البرنامج:
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 DEBUG='ctx-module*' ويمكنك رؤية أسماء الملفات التي تحاول تحميلها.
يحتوي Pythonmonkey على مصحح أخطاء خط أوامر JavaScript Like Like GDB يسمى 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 في Reply--help--inspect-r لتحميل وحدة قبل البرنامج أو تشغيل الاستبدال-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'
>