استكشاف متعمق لـ Tornado، وهو إطار عمل ويب ومكتبة شبكات غير متزامنة في بايثون. تعلم كيفية بناء تطبيقات قابلة للتطوير وعالية الأداء مع شروحات مفصلة وأمثلة وأفضل الممارسات.
وثائق Tornado: دليل شامل للمطورين حول العالم
Tornado هو إطار عمل ويب ومكتبة شبكات غير متزامنة في بايثون، تم تطويره في الأصل في FriendFeed. وهو مناسب بشكل خاص للاستقصاء الطويل (long-polling)، و WebSockets، والتطبيقات الأخرى التي تتطلب اتصالاً طويل الأمد بكل مستخدم. إن إدخال/إخراج الشبكة غير الحاجب (non-blocking) يجعله قابلاً للتطوير بدرجة كبيرة وخيارًا قويًا لبناء تطبيقات ويب عالية الأداء. سيرشدك هذا الدليل الشامل عبر المفاهيم الأساسية لـ Tornado ويقدم أمثلة عملية لتبدأ.
ما هو Tornado؟
في جوهره، Tornado هو إطار عمل ويب ومكتبة شبكات غير متزامنة. على عكس أطر عمل الويب المتزامنة التقليدية، يستخدم Tornado بنية أحادية الخيط قائمة على حلقة الأحداث. هذا يعني أنه يمكنه التعامل مع العديد من الاتصالات المتزامنة دون الحاجة إلى خيط لكل اتصال، مما يجعله أكثر كفاءة وقابلية للتطوير.
الميزات الرئيسية لـ Tornado:
- شبكات غير متزامنة: تم بناء جوهر Tornado حول الإدخال/الإخراج غير المتزامن، مما يسمح له بمعالجة آلاف الاتصالات المتزامنة بكفاءة.
- إطار عمل الويب: يتضمن ميزات مثل معالجات الطلبات، والتوجيه، والقوالب، والمصادقة، مما يجعله إطار عمل ويب متكامل.
- دعم WebSocket: يوفر Tornado دعمًا ممتازًا لـ WebSockets، مما يتيح الاتصال في الوقت الفعلي بين الخادم والعملاء.
- خفيف وسريع: صُمم Tornado للأداء العالي، وهو خفيف الوزن وفعال، مما يقلل من الحمل الزائد ويزيد من الإنتاجية.
- سهل الاستخدام: على الرغم من ميزاته المتقدمة، فإن Tornado سهل التعلم والاستخدام نسبيًا، مع واجهة برمجة تطبيقات واضحة وموثقة جيدًا.
إعداد بيئة Tornado الخاصة بك
قبل الغوص في تطوير Tornado، ستحتاج إلى إعداد بيئتك. إليك دليل خطوة بخطوة:
- تثبيت بايثون: تأكد من أن لديك بايثون 3.6 أو أعلى مثبتًا. يمكنك تنزيله من موقع بايثون الرسمي (python.org).
- إنشاء بيئة افتراضية (موصى به): استخدم
venv
أوvirtualenv
لإنشاء بيئة معزولة لمشروعك:python3 -m venv myenv source myenv/bin/activate # على Linux/macOS myenv\Scripts\activate # على Windows
- تثبيت Tornado: قم بتثبيت Tornado باستخدام pip:
pip install tornado
تطبيقك الأول مع Tornado
لنقم بإنشاء تطبيق "أهلاً بالعالم!" بسيط باستخدام Tornado. أنشئ ملفًا باسم app.py
وأضف الكود التالي:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, World!")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
الآن، قم بتشغيل التطبيق من الطرفية الخاصة بك:
python app.py
افتح متصفح الويب الخاص بك وانتقل إلى http://localhost:8888
. يجب أن ترى رسالة "Hello, World!".
الشرح:
tornado.ioloop
: حلقة الأحداث الأساسية التي تتعامل مع العمليات غير المتزامنة.tornado.web
: يوفر مكونات إطار عمل الويب، مثل معالجات الطلبات والتوجيه.MainHandler
: معالج طلبات يحدد كيفية التعامل مع طلبات HTTP الواردة. يتم استدعاء التابعget()
لطلبات GET.tornado.web.Application
: ينشئ تطبيق Tornado، ويربط أنماط عناوين URL بمعالجات الطلبات.app.listen(8888)
: يبدأ الخادم، ويستمع للاتصالات الواردة على المنفذ 8888.tornado.ioloop.IOLoop.current().start()
: يبدأ حلقة الأحداث، التي تعالج الطلبات الواردة وتتعامل مع العمليات غير المتزامنة.
معالجات الطلبات والتوجيه
معالجات الطلبات هي أساس تطبيقات ويب Tornado. هي تحدد كيفية التعامل مع طلبات HTTP الواردة بناءً على عنوان URL. يقوم التوجيه بربط عناوين URL بمعالجات طلبات محددة.
تحديد معالجات الطلبات:
لإنشاء معالج طلبات، قم بإنشاء فئة فرعية من tornado.web.RequestHandler
وقم بتنفيذ توابع HTTP المناسبة (get
، post
، put
، delete
، إلخ).
class MyHandler(tornado.web.RequestHandler):
def get(self):
self.write("This is a GET request.")
def post(self):
data = self.request.body.decode('utf-8')
self.write(f"Received POST data: {data}")
التوجيه:
يتم تكوين التوجيه عند إنشاء tornado.web.Application
. أنت تقدم قائمة من الصفوف (tuples)، حيث يحتوي كل صف على نمط URL ومعالج الطلب المقابل.
app = tornado.web.Application([
(r"/", MainHandler),
(r"/myhandler", MyHandler),
])
أنماط URL:
أنماط URL هي تعبيرات نمطية. يمكنك استخدام مجموعات التعبيرات النمطية لالتقاط أجزاء من عنوان URL وتمريرها كوسائط إلى توابع معالج الطلب.
class UserHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.write(f"User ID: {user_id}")
app = tornado.web.Application([
(r"/user/([0-9]+)", UserHandler),
])
في هذا المثال، /user/([0-9]+)
يطابق عناوين URL مثل /user/123
. الجزء ([0-9]+)
يلتقط رقمًا واحدًا أو أكثر ويمررها كوسيط user_id
إلى تابع get
الخاص بـ UserHandler
.
القوالب
يتضمن Tornado محرك قوالب بسيط وفعال. تُستخدم القوالب لإنشاء HTML ديناميكيًا، وفصل منطق العرض عن منطق التطبيق.
إنشاء القوالب:
عادة ما يتم تخزين القوالب في ملفات منفصلة (على سبيل المثال، index.html
). إليك مثال بسيط:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Welcome, {{ name }}!</h1>
<p>Today is {{ today }}.</p>
</body>
</html>
{{ name }}
و {{ today }}
هي عناصر نائبة سيتم استبدالها بقيم فعلية عند عرض القالب.
عرض القوالب:
لعرض قالب، استخدم التابع render()
في معالج الطلب الخاص بك:
class TemplateHandler(tornado.web.RequestHandler):
def get(self):
name = "John Doe"
today = "2023-10-27"
self.render("index.html", name=name, today=today)
تأكد من تكوين إعداد template_path
بشكل صحيح في إعدادات تطبيقك. افتراضيًا، يبحث Tornado عن القوالب في دليل يسمى templates
في نفس دليل ملف التطبيق الخاص بك.
app = tornado.web.Application([
(r"/template", TemplateHandler),
], template_path="templates")
صيغة القوالب:
تدعم قوالب Tornado ميزات متنوعة، بما في ذلك:
- المتغيرات:
{{ variable }}
- تدفق التحكم:
{% if condition %} ... {% else %} ... {% end %}
,{% for item in items %} ... {% end %}
- الدوال:
{{ function(argument) }}
- التضمينات:
{% include "another_template.html" %}
- التهريب (Escaping): يقوم Tornado تلقائيًا بتهريب كيانات HTML لمنع هجمات البرمجة عبر المواقع (XSS). يمكنك تعطيل التهريب باستخدام
{% raw variable %}
.
العمليات غير المتزامنة
تكمن قوة Tornado في قدراته غير المتزامنة. تسمح العمليات غير المتزامنة لتطبيقك بأداء عمليات إدخال/إخراج غير حاجزة، مما يحسن الأداء وقابلية التوسع. هذا مفيد بشكل خاص للمهام التي تنطوي على انتظار موارد خارجية، مثل استعلامات قاعدة البيانات أو طلبات الشبكة.
@tornado.gen.coroutine
:
يسمح لك المُزخرف @tornado.gen.coroutine
بكتابة كود غير متزامن باستخدام الكلمة المفتاحية yield
. هذا يجعل الكود غير المتزامن يبدو ويتصرف بشكل أشبه بالكود المتزامن، مما يحسن من قابلية القراءة والصيانة.
import tornado.gen
import tornado.httpclient
class AsyncHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
http_client = tornado.httpclient.AsyncHTTPClient()
response = yield http_client.fetch("http://example.com")
self.write(response.body.decode('utf-8'))
في هذا المثال، http_client.fetch()
هي عملية غير متزامنة تُرجع كائن Future
. تقوم الكلمة المفتاحية yield
بتعليق تنفيذ الروتين المساعد (coroutine) حتى يتم حل الـ Future
. بمجرد حل الـ Future
، يستأنف الروتين المساعد ويتم كتابة جسم الاستجابة إلى العميل.
tornado.concurrent.Future
:
يمثل كائن Future
نتيجة عملية غير متزامنة قد لا تكون متاحة بعد. يمكنك استخدام كائنات Future
لربط العمليات غير المتزامنة معًا والتعامل مع الأخطاء.
tornado.ioloop.IOLoop
:
IOLoop
هو قلب محرك Tornado غير المتزامن. يراقب واصفات الملفات والمقابس للأحداث ويرسلها إلى المعالجات المناسبة. عادةً ما لا تحتاج إلى التفاعل مع IOLoop
مباشرةً، ولكن من المهم فهم دوره في التعامل مع العمليات غير المتزامنة.
WebSockets
يوفر Tornado دعمًا ممتازًا لـ WebSockets، مما يتيح الاتصال في الوقت الفعلي بين الخادم والعملاء. تعتبر WebSockets مثالية للتطبيقات التي تتطلب اتصالًا ثنائي الاتجاه ومنخفض الكمون، مثل تطبيقات الدردشة والألعاب عبر الإنترنت ولوحات المعلومات في الوقت الفعلي.
إنشاء معالج WebSocket:
لإنشاء معالج WebSocket، قم بإنشاء فئة فرعية من tornado.websocket.WebSocketHandler
وقم بتنفيذ التوابع التالية:
open()
: يُستدعى عند إنشاء اتصال WebSocket جديد.on_message(message)
: يُستدعى عند استلام رسالة من العميل.on_close()
: يُستدعى عند إغلاق اتصال WebSocket.
import tornado.websocket
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket opened")
def on_message(self, message):
self.write_message(f"You sent: {message}")
def on_close(self):
print("WebSocket closed")
def check_origin(self, origin):
return True # تمكين اتصالات WebSocket عبر المصادر
دمج WebSockets في تطبيقك:
أضف معالج WebSocket إلى تكوين التوجيه في تطبيقك:
app = tornado.web.Application([
(r"/ws", WebSocketHandler),
])
التنفيذ من جانب العميل:
من جانب العميل، يمكنك استخدام JavaScript لإنشاء اتصال WebSocket وإرسال/استقبال الرسائل:
const websocket = new WebSocket("ws://localhost:8888/ws");
websocket.onopen = () => {
console.log("WebSocket connection established");
websocket.send("Hello from the client!");
};
websocket.onmessage = (event) => {
console.log("Received message:", event.data);
};
websocket.onclose = () => {
console.log("WebSocket connection closed");
};
المصادقة والأمان
الأمان هو جانب حاسم في تطوير تطبيقات الويب. يوفر Tornado العديد من الميزات لمساعدتك في تأمين تطبيقاتك، بما في ذلك المصادقة والترخيص والحماية من الثغرات الأمنية الشائعة على الويب.
المصادقة:
المصادقة هي عملية التحقق من هوية المستخدم. يوفر Tornado دعمًا مدمجًا لمختلف أنظمة المصادقة، بما في ذلك:
- المصادقة القائمة على ملفات تعريف الارتباط (Cookies): تخزين بيانات اعتماد المستخدم في ملفات تعريف الارتباط.
- مصادقة الطرف الثالث (OAuth): التكامل مع منصات التواصل الاجتماعي الشهيرة مثل Google و Facebook و Twitter.
- مفاتيح API: استخدام مفاتيح API لمصادقة طلبات API.
الترخيص:
الترخيص هو عملية تحديد ما إذا كان لدى المستخدم إذن للوصول إلى مورد معين. يمكنك تنفيذ منطق الترخيص في معالجات الطلبات الخاصة بك لتقييد الوصول بناءً على أدوار المستخدم أو أذوناته.
أفضل ممارسات الأمان:
- الحماية من البرمجة عبر المواقع (XSS): يقوم Tornado تلقائيًا بتهريب كيانات HTML لمنع هجمات XSS. استخدم دائمًا التابع
render()
لعرض القوالب وتجنب إنشاء HTML مباشرة في معالجات الطلبات الخاصة بك. - الحماية من تزوير الطلبات عبر المواقع (CSRF): قم بتمكين حماية CSRF في إعدادات تطبيقك لمنع هجمات CSRF.
- HTTPS: استخدم دائمًا HTTPS لتشفير الاتصال بين الخادم والعملاء.
- التحقق من صحة الإدخال: تحقق من صحة جميع مدخلات المستخدم لمنع هجمات الحقن وغيرها من الثغرات الأمنية.
- عمليات التدقيق الأمني المنتظمة: قم بإجراء عمليات تدقيق أمني منتظمة لتحديد ومعالجة الثغرات الأمنية المحتملة.
النشر
يتضمن نشر تطبيق Tornado عدة خطوات، بما في ذلك تكوين خادم ويب، وإعداد مدير عمليات، وتحسين الأداء.
خادم الويب:
يمكنك نشر Tornado خلف خادم ويب مثل Nginx أو Apache. يعمل خادم الويب كوكيل عكسي (reverse proxy)، حيث يقوم بإعادة توجيه الطلبات الواردة إلى تطبيق Tornado.
مدير العمليات:
يمكن استخدام مدير عمليات مثل Supervisor أو systemd لإدارة عملية Tornado، مما يضمن إعادة تشغيلها تلقائيًا في حالة تعطلها.
تحسين الأداء:
- استخدام حلقة أحداث جاهزة للإنتاج: استخدم حلقة أحداث جاهزة للإنتاج مثل
uvloop
لتحسين الأداء. - تمكين ضغط gzip: قم بتمكين ضغط gzip لتقليل حجم استجابات HTTP.
- التخزين المؤقت للملفات الثابتة: قم بالتخزين المؤقت للملفات الثابتة لتقليل الحمل على الخادم.
- مراقبة الأداء: راقب أداء تطبيقك باستخدام أدوات مثل New Relic أو Prometheus.
التدويل (i18n) والتعريب (l10n)
عند بناء تطبيقات لجمهور عالمي، من المهم مراعاة التدويل (i18n) والتعريب (l10n). التدويل هو عملية تصميم تطبيق بحيث يمكن تكييفه مع مختلف اللغات والمناطق دون تغييرات هندسية. التعريب هو عملية تكييف تطبيق مدوّل للغة أو منطقة معينة عن طريق إضافة مكونات خاصة باللغة المحلية وترجمة النصوص.
Tornado و i18n/l10n
لا يحتوي Tornado نفسه على مكتبات مدمجة للتدويل/التعريب. ومع ذلك، يمكنك بسهولة دمج مكتبات بايثون القياسية مثل `gettext` أو أطر عمل أكثر تطوراً مثل Babel للتعامل مع التدويل/التعريب داخل تطبيق Tornado الخاص بك.
مثال باستخدام `gettext`:
1. **إعداد اللغات المحلية الخاصة بك:** أنشئ أدلة لكل لغة تريد دعمها، تحتوي على كتالوجات الرسائل (عادةً ملفات `.mo`).
locales/
en/LC_MESSAGES/messages.mo
fr/LC_MESSAGES/messages.mo
de/LC_MESSAGES/messages.mo
2. **استخراج السلاسل النصية القابلة للترجمة:** استخدم أداة مثل `xgettext` لاستخراج السلاسل النصية القابلة للترجمة من كود بايثون الخاص بك إلى ملف `.po` (Portable Object). سيحتوي هذا الملف على السلاسل الأصلية والعناصر النائبة للترجمات.
xgettext -d messages -o locales/messages.po your_tornado_app.py
3. **ترجمة السلاسل النصية:** ترجم السلاسل النصية في ملفات `.po` لكل لغة.
4. **تجميع الترجمات:** قم بتجميع ملفات `.po` إلى ملفات `.mo` (Machine Object) التي يستخدمها `gettext` في وقت التشغيل.
msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo
5. **التكامل مع تطبيق Tornado الخاص بك:**
import gettext
import locale
import os
import tornado.web
class BaseHandler(tornado.web.RequestHandler):
def initialize(self):
try:
locale.setlocale(locale.LC_ALL, self.get_user_locale().code)
except locale.Error:
# معالجة الحالات التي لا يدعمها النظام
print(f"Locale {self.get_user_locale().code} not supported")
translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
translation.install()
self._ = translation.gettext
def get_current_user_locale(self):
# منطق لتحديد لغة المستخدم (على سبيل المثال، من ترويسة Accept-Language، إعدادات المستخدم، إلخ)
# هذا مثال مبسط - ستحتاج إلى حل أكثر قوة
accept_language = self.request.headers.get('Accept-Language', 'en')
return tornado.locale.get(accept_language.split(',')[0].split(';')[0])
class MainHandler(BaseHandler):
def get(self):
self.render("index.html", _=self._)
settings = {
"template_path": os.path.join(os.path.dirname(__file__), "templates"),
}
app = tornado.web.Application([
(r"/", MainHandler),
], **settings)
6. **تعديل قوالبك:** استخدم الدالة `_()` (المرتبطة بـ `gettext.gettext`) لوضع علامة على السلاسل النصية للترجمة في قوالبك.
<h1>{{ _("Welcome to our website!") }}</h1>
<p>{{ _("This is a translated paragraph.") }}</p>
اعتبارات هامة للجماهير العالمية:
- **ترميز الأحرف:** استخدم دائمًا ترميز UTF-8 لدعم مجموعة واسعة من الأحرف.
- **تنسيق التاريخ والوقت:** استخدم تنسيق التاريخ والوقت الخاص باللغة المحلية. يمكن استخدام دوال `strftime` و `strptime` في بايثون مع إعدادات اللغة المحلية.
- **تنسيق الأرقام:** استخدم تنسيق الأرقام الخاص باللغة المحلية (مثل فواصل الكسور العشرية، فواصل الآلاف). توفر وحدة `locale` دوال لهذا الغرض.
- **تنسيق العملة:** استخدم تنسيق العملة الخاص باللغة المحلية. ضع في اعتبارك استخدام مكتبة مثل `Babel` للتعامل مع العملات بشكل أكثر تقدمًا.
- **اللغات من اليمين إلى اليسار (RTL):** دعم لغات RTL مثل العربية والعبرية. قد يتطلب هذا عكس تخطيط موقع الويب الخاص بك.
- **جودة الترجمة:** استخدم مترجمين محترفين لضمان ترجمات دقيقة ومناسبة ثقافيًا. يمكن أن تكون الترجمة الآلية نقطة انطلاق جيدة، لكنها غالبًا ما تتطلب مراجعة بشرية.
- **الكشف عن لغة المستخدم:** قم بتنفيذ كشف قوي عن اللغة المحلية بناءً على تفضيلات المستخدم أو إعدادات المتصفح أو عنوان IP. وفر طريقة للمستخدمين لتحديد لغتهم المفضلة يدويًا.
- **الاختبار:** اختبر تطبيقك جيدًا مع لغات محلية مختلفة للتأكد من عرض كل شيء بشكل صحيح.
مواضيع متقدمة
صفحات الخطأ المخصصة:
يمكنك تخصيص صفحات الخطأ التي يعرضها Tornado عند حدوث خطأ. يتيح لك ذلك توفير تجربة أكثر سهولة في الاستخدام وتضمين معلومات تصحيح الأخطاء.
الإعدادات المخصصة:
يمكنك تحديد إعدادات مخصصة في تكوين تطبيقك والوصول إليها في معالجات الطلبات الخاصة بك. هذا مفيد لتخزين المعلمات الخاصة بالتطبيق، مثل سلاسل اتصال قاعدة البيانات أو مفاتيح API.
الاختبار:
اختبر تطبيقات Tornado الخاصة بك جيدًا للتأكد من أنها تعمل بشكل صحيح وآمن. استخدم اختبارات الوحدة واختبارات التكامل واختبارات النهاية إلى النهاية لتغطية جميع جوانب تطبيقك.
الخاتمة
Tornado هو إطار عمل ويب قوي ومتعدد الاستخدامات ومناسب تمامًا لبناء تطبيقات ويب قابلة للتطوير وعالية الأداء. إن بنيته غير المتزامنة ودعمه لـ WebSocket وواجهة برمجة التطبيقات سهلة الاستخدام تجعله خيارًا شائعًا للمطورين في جميع أنحاء العالم. باتباع الإرشادات والأمثلة الواردة في هذا الدليل الشامل، يمكنك البدء في بناء تطبيقات Tornado الخاصة بك والاستفادة من ميزاته العديدة.
تذكر مراجعة وثائق Tornado الرسمية للحصول على أحدث المعلومات وأفضل الممارسات. برمجة سعيدة!