في جملة واحدة
ملعب بايثون يسمح لك بكتابة وتشغيل كود بايثون حقيقي، مع كامل مكتباته الشهيرة، مباشرة في متصفح الويب الخاص بك دون الحاجة إلى خادم أو أي تثبيت محلي، كل ذلك بفضل سحر تقنية WebAssembly.
المشكلة التي يحلها
خلال معظم تاريخ الويب، كان المتصفح هو مملكة JavaScript. إذا أردت تشغيل كود على صفحة ويب، كان عليك كتابته بلغة JS. نقطة. إذا كنت من مبرمجي بايثون وأردت، على سبيل المثال، تشغيل سكربت لتحليل البيانات وعرض النتائج على الإنترنت، كان أمامك موال طويل وعريض. كنت ستكتب كود البايثون، تشغله على خادم، ثم تجعل موقعك يجلب النتائج. نموذج العميل-الخادم هذا قوي، لكنه يمثل عبئًا كبيرًا لمجرد تجربة سكربت سريع أو مشاركة مقتطف كود.
المحاولات الأولى لكسر هذا القالب كانت ذكية ولكنها غير مكتملة. مشاريع مثل Brython أو Skulpt كانت في جوهرها مترجمات من بايثون إلى JavaScript. كانت تسمح لك بكتابة صيغة تشبه بايثون يتم تحويلها إلى JavaScript ثم تنفيذها بواسطة المتصفح. كان هذا رائعًا للأغراض التعليمية، لكنه لم يكن بايثون حقيقي. كان برنامج JS يرتدي قناع بايثون. الأهم من ذلك، أن هذا النهج كان له عيبان رئيسيان:
- لم يكن يتصرف دائمًا تمامًا مثل مترجم بايثون الرسمي (المعروف باسم CPython). يمكن أن تؤدي الاختلافات الدقيقة إلى إرباكك.
- لم يتمكن من تشغيل النظام البيئي الضخم لمكتبات بايثون التي تعتمد على ملحقات لغة C (C extensions) لتحسين الأداء، مثل عمالقة علوم البيانات NumPy و Pandas.
كانت المشكلة الأساسية هي كيفية تشغيل مترجم CPython الفعلي الرسمي - ذلك الذي تقوم بتنزيله من python.org - داخل بيئة "صندوق الرمل" (sandbox) الآمنة والمحكمة للمتصفح. حل هذه المشكلة سيفتح عالمًا من الاحتمالات: النماذج الأولية الفورية، والأدوات التعليمية التي لا تتطلب أي إعداد، وأمثلة الكود القابلة للمشاركة والتشغيل حقًا للتعاون وتقارير الأخطاء. سيعني ذلك أن بايثون يمكن أن يصبح أخيرًا مواطنًا من الدرجة الأولى داخل المتصفح، وليس مجرد لغة تعيش على خادم بعيد.
كيف تعمل الأمور تحت الغطاء
إن تشغيل CPython، وهو برنامج مكتوب بلغة C، داخل متصفح ويب يتحدث لغة JavaScript يبدو وكأنه نوع من الكيمياء الرقمية. وهو كذلك بالفعل! حجر الفلاسفة في هذه العملية هو تقنية تسمى WebAssembly.
البطل: WebAssembly (Wasm)
WebAssembly، أو Wasm اختصارًا، هو الخلطة السرية. فكر فيه ليس كلغة تكتب بها، بل كلغة تقوم بالترجمة إليها. إنه تنسيق تعليمات ثنائي منخفض المستوى يمكن لمتصفحات الويب الحديثة تنفيذه بسرعة شبه أصلية. وهو مصمم ليكون هدف ترجمة محمولًا للغات عالية المستوى مثل C و C++ و Rust.
لذا، بدلاً من أن يفهم محرك JavaScript في المتصفح لغة JavaScript فقط، أصبح يفهم الآن أيضًا هذا الكود الثنائي (bytecode) الخاص بـ Wasm، المُحسَّن للغاية ومنخفض المستوى. هذا يعني أنه يمكنك أخذ تطبيق معقد مكتوب بلغة C، وباستخدام الأدوات المناسبة، ترجمته إلى ملف .wasm يمكن تشغيله داخل علامة تبويب في المتصفح.
ترجمة CPython إلى Wasm
هذه هي لحظة "وجدتها!". المترجم القياسي والأكثر استخدامًا لبايثون يسمى CPython لأنه مكتوب بلغة C. وبما أنه يمكننا ترجمة كود C إلى WebAssembly، فمن المنطقي أنه يمكننا ترجمة مترجم CPython بالكامل إلى WebAssembly.
هذه العملية، التي تقودها مشاريع مثل Pyodide، تأخذ الكود المصدري بلغة C لمترجم بايثون وتمرره عبر مترجم خاص (مثل Emscripten). الناتج ليس ملفًا تنفيذيًا عاديًا مثل .exe لنظام التشغيل الخاص بك، بل ملف cpython.wasm. يحتوي هذا الملف على بيئة تشغيل بايثون بأكملها: آلية تحليل الكود الخاص بك، وإدارة الذاكرة، وتنفيذ تعليماتك، كل ذلك مجمّع في تنسيق يمكن للمتصفح تشغيله.
نظام ملفات في الذاكرة
عندما يقوم متصفحك بتحميل مترجم cpython.wasm هذا، فإنه مجرد مترجم. يعمل في صندوق رمل صارم ولا يملك أي وصول لنظام الملفات الفعلي على جهازك (وهذا مكسب أمني هائل). إذن كيف يعمل import numpy أو حتى import math؟ تحتاج تلك المكتبات إلى وجود ملفات في مكان ما.
الحل هو نظام ملفات افتراضي. يتم تخصيص جزء من ذاكرة المتصفح ليعمل كقرص صلب. قبل أن يقوم الملعب بتشغيل الكود الخاص بك، يقوم بتحميل حزمة مجمّعة مسبقًا من مكتبة بايثون القياسية ونسخ Wasm أخرى مسبقة الترجمة من الحزم الشائعة (مثل NumPy) في نظام الملفات هذا الموجود في الذاكرة. عندما يقوم كود بايثون الخاص بك الذي يعمل في Wasm بتنفيذ import numpy، يبحث المترجم داخل نظام الملفات الافتراضي هذا، ويجد الملفات اللازمة، ويقوم بتحميلها، تمامًا كما يفعل على جهازك المحلي.
جسر بين عالمين: الاتصال بين JS <-> Python
لدينا الآن مترجم بايثون يعمل كـ Wasm داخل محرك JS الخاص بالمتصفح. كيف ندخل الكود إليه ونخرج النتائج منه؟ يتم التعامل مع هذا بواسطة طبقة "ربط" (glue) مكتوبة بلغة JavaScript.
يبدو سير العمل كالتالي:
- التهيئة (Initialization): يقوم متصفحك بتحميل الصفحة. يقوم كود JavaScript بتنزيل مترجم
cpython.wasmوحزمة نظام الملفات الافتراضي. - تسليم المهمة (Hand-off): تكتب كود بايثون الخاص بك، على سبيل المثال
print("Hello from Python!")، في مربع نص وتضغط على "Run". - طبقة الربط (The Glue): تأخذ دالة JavaScript الكود الخاص بك كسلسلة نصية وتمررها إلى دالة خاصة مكشوفة من وحدة Wasm.
- التنفيذ في Wasm: داخل بيئة Wasm، ينبض مترجم CPython بالحياة. يقوم بتحليل سلسلة الكود الخاصة بك، وتنفيذها، وإنتاج المخرجات (في هذه الحالة، كتابة "Hello from Python!" إلى مجرى الإخراج القياسي الخاص به،
stdout). - التقاط المخرجات (Capturing Output): تم تصميم كود الربط في JS لاعتراض أي شيء تكتبه وحدة Wasm إلى
stdoutأوstderrوالتقاطه كسلسلة نصية. - رحلة العودة (The Return Trip): يأخذ كود JS تلك السلسلة النصية الملتقطة ويعرضها في منطقة الإخراج على صفحة الويب. بالنسبة للبيانات الأكثر تعقيدًا، تقوم طبقة الربط بعملية ترجمة، محولةً كائنات بايثون مثل القواميس والقوائم إلى ما يعادلها في JavaScript (
dict->Object،list->Array).
هذا الجسر يسمح للعالمين المنفصلين - DOM الخاص بالمتصفح الذي تديره JavaScript وبيئة تشغيل بايثون المعزولة في Wasm - بالتواصل بسلاسة.
قصص من الواقع
مقتطف كود في مقابلة عمل لعلوم البيانات
كانت سارة في الجولة النهائية من مقابلة فنية لوظيفة في مجال علوم البيانات. قال المحاور، وهو يشارك شاشته: "هل يمكنك كتابة دالة بايثون سريعة باستخدام NumPy لحساب متوسط متحرك من ثلاث نقاط على قائمة من الأرقام؟" بدلاً من التخبط في محرر نصوص مشترك والقول "حسنًا، ستقوم باستيراد NumPy هكذا..."، طلبت سارة التحكم، فتحت ملعب بايثون في المتصفح، وكتبت الكود. عرّفت الدالة، وأنشأت مصفوفة عينة، وشغّلتها، وأظهرت الناتج الصحيح على الفور. ثم شاركت رابط حلها العامل في الدردشة. لم يكن المحاور معجبًا بالكود الصحيح فحسب، بل أيضًا بالعرض العملي والسريع.
الدرس: ملعب المتصفح هو البيئة المثالية والمكتفية ذاتيًا لإثبات مفهوم أو اختبار خوارزمية دون متاعب الإعداد المحلي، مما يجعله أداة قوية للبرمجة الحية والتعاون.
تقرير الخطأ الذي كان مفيدًا حقًا
اكتشف أليكس خطأً غريبًا في حالة نادرة (edge-case) في مكتبة مفتوحة المصدر لتصوير البيانات. كان المخطط البياني يظهر بشكل غير صحيح فقط عندما تكون بيانات الإدخال عبارة عن قائمة من الصفوف (tuples) تحتوي على قيمة None. قدم تقرير مشكلة (issue) على GitHub، ولكن بدلاً من مجرد وصف المشكلة، فتح ملعب بايثون. قام بلصق الحد الأدنى من الكود اللازم لإعادة إنتاج الخطأ — جملة الاستيراد، وهيكل البيانات الإشكالي بالضبط، واستدعاء الدالة الذي أثار الخطأ. قام بتشغيله، ورأى رسالة الخطأ، ولصق رابط الملعب في تقرير الخطأ الخاص به مع عنوان "مثال بسيط قابل للتكرار". تمكن مشرف المكتبة من النقر على الرابط، ورؤية الخطأ على الفور، والبدء في تصحيحه دون أي إعداد.
الدرس: مقتطف الكود القابل للمشاركة والتشغيل هو المعيار الذهبي لتقارير الأخطاء. فهو يزيل الغموض ويقلل بشكل كبير من العائق أمام الآخرين للمساعدة.
لحظة "كيف كان هذا يعمل مرة أخرى؟" السريعة
كانت مايا، وهي مطورة واجهة أمامية، في منتصف عملها على مكون React معقد. كانت بحاجة إلى تمرير بعض البيانات إلى واجهة برمجة تطبيقات خلفية (API) تتوقع بنية قاموس بايثون معينة. لم تستطع تذكر صيغة الـ dictionary comprehension تمامًا. بدلاً من كسر تدفق عملها بفتح طرفية، وإنشاء ملف جديد، وتشغيله، فتحت ببساطة علامة تبويب جديدة في المتصفح بها ملعب بايثون. كتبت squares = {x: x*x for x in range(5)} و print(squares)، ضغطت على "تشغيل"، وحصلت على إجابتها في أقل من عشر ثوانٍ. حصلت على الصيغة، أغلقت علامة التبويب، وعادت مباشرة إلى كود JavaScript الخاص بها.
الدرس: ملاعب المتصفح هي أسرع طريقة "لتبديل السياق" والتحقق من الصيغة أو السلوك في لغة أخرى دون تعطيل سير عملك التطويري الرئيسي.
أخطاء وفخاخ شائعة
- توقع الوصول إلى الملفات المحلية. لا يمكنك كتابة
open('C:\\Users\\Me\\my_data.csv', 'r'). يعمل الملعب في صندوق رمل آمن بالمتصفح وليس لديه أي وصول على الإطلاق لملفات جهاز الكمبيوتر الخاص بك. يجب عليك لصق بياناتك مباشرة في الكود الخاص بك. - محاولة
pip installلأي شيء. تأتي البيئة مع مجموعة مدمجة ومترجمة مسبقًا من الحزم الشائعة. لا يمكنك تثبيت حزم عشوائية من مؤشر حزم بايثون (PyPI)، خاصة تلك التي تحتوي على تبعيات C معقدة لم يتم ترجمتها إلى Wasm. - نسيان أنها جلسة معزولة. الكود والمتغيرات والمكتبات التي استوردتها موجودة فقط طوال عمر الصفحة. إذا قمت بتحديث علامة تبويب المتصفح، فسيتم مسح كل شيء. إنها بيئة عديمة الحالة (stateless).
- تشغيل كود معطِّل أو حلقات لا نهائية. أمر بريء المظهر مثل
while True: passسيستولي على الخيط الرئيسي للمتصفح ويجمد علامة التبويب بأكملها. سيتخلى المتصفح في النهاية ويطلب منك إغلاق الصفحة. الملعب مخصص للسكربتات السريعة، وليس للمهام طويلة الأمد والمكثفة حسابيًا. - تجاهل تكلفة بدء التشغيل. بينما يكون تنفيذ Wasm سريعًا، فإن تحميل مترجم بايثون ونظام الملفات الذي يبلغ حجمه عدة ميغابايت في المتصفح يستغرق لحظة. سيكون التشغيل الأول على صفحة تم تحميلها حديثًا أبطأ دائمًا من عمليات التشغيل اللاحقة.
لماذا يجب أن تضعه على رادارك
يجب أن يكون ملعب بايثون المستند إلى المتصفح في صندوق أدوات كل مطور الافتراضي. إنه المعادل الرقمي لقطعة ورق مسودة لتدوين الأكواد.
فكر فيه عندما:
- تحتاج إلى اختبار خوارزمية صغيرة أو تحويل بيانات دون طقوس إنشاء ملف
.py. - تقوم بتدريس أو شرح مفهوم في بايثون وتريد تقديم مثال حي وتفاعلي يمكن لأي شخص تشغيله والتلاعب به.
- أنت مطور لا تستخدم بايثون وتحتاج إلى فهم أو إنشاء نموذج أولي لجزء من منطق بايثون من زميل لك.
- أنت على جهاز مقيّد الصلاحيات (مثل جهاز Chromebook أو جهاز الشركة) حيث لا يمكنك تثبيت بيئة بايثون كاملة.
- تريد تجربة مكتبة مثل NumPy أو Pandas لمهمة صغيرة دون متاعب إدارة بيئة
venvأوcondaمحلية.
إنه يمثل نقلة نوعية: جلب الحوسبة الجادة والأنظمة البيئية الشائعة للمطورين مباشرة إلى المنصة المنتشرة في كل مكان وهي متصفح الويب.
للتعمق أكثر
- WebAssembly.org — الموقع الرسمي لكل ما يتعلق بـ Wasm، بما في ذلك المواصفات والتوثيق.
- The Pyodide Project — مشروع رائد لترجمة بايثون والمكدس العلمي إلى WebAssembly. المحرك وراء العديد من أدوات بايثون داخل المتصفح.
- MDN WebAssembly Docs — توثيق Mozilla الممتاز وسهل الاستخدام للمطورين حول استخدام WebAssembly في المتصفح.
- CPython source code — للشجعان حقًا، هذا هو الكود المصدري بلغة C لمترجم بايثون نفسه.
- Emscripten — مجموعة الأدوات المستخدمة لترجمة كود C/C++ إلى WebAssembly، وهي مكون رئيسي في جلب CPython إلى المتصفح.
كيف يفهم المحرر الشيفرة
ألوان الصياغة تأتي من محلل اللغة، لا من تشغيل البرنامج. يتعرف CodeMirror وLezer على الرموز والبنية محليًا في المتصفح. تجمع الاقتراحات الكلمات المحجوزة والأسماء المحلية عند دعمها والمقاطع الجاهزة ومرجعًا مدمجًا صغيرًا؛ ويكشف المرور فوق رمز موثق عن توقيعه. الاقتراح لا يضمن وجود الواجهة في بيئة التنفيذ. يكتشف المحلل أخطاء الصياغة عند دعمها، لكنه لا يحل محل فحص الأنواع أو التشغيل: قد تفشل شيفرة سليمة نحويًا. يستخدم Ruby وLua أوضاعًا قائمة على الرموز وتشخيصات أكثر محدودية. لا يوجد خادم لغة بعيد، ولا تحتاج الشيفرة إلى مغادرة الجهاز.
CodeMirror & Lezer: MIT.