1. مقدمة
Python هي لغة برمجة شائعة مفتوحة المصدر يستخدمها علماء البيانات ومطورو تطبيقات الويب ومسؤولو النظم وغيرهم.
Cloud Functions هي منصة حوسبة بدون خادم تعتمد على الأحداث. تسمح لك ميزة Cloud Functions بكتابة الرمز البرمجي بدون القلق بشأن توفير الموارد أو التطوير لتلبية المتطلبات المتغيّرة.
هناك نوعان من دوال السحابة:
- تستجيب دوال HTTP لطلبات HTTP. ستنشئ اثنين في هذا الدرس التطبيقي حول الترميز.
- يتم تفعيل وظائف الخلفية من خلال أحداث، مثلاً رسالة يتم نشرها على Cloud Pub/Sub أو ملف يتم تحميله إلى Cloud Storage. لم نتناول ذلك في هذا التمرين المعملي، ولكن يمكنك قراءة المزيد من خلال المستندات.
سيساعدك هذا الدرس التطبيقي في إنشاء الدوال السحابية في بايثون.
ما الذي ستقوم ببنائه
في هذا الدرس التطبيقي حول الترميز، ستنشر دالة Cloud عند استدعائها عبر HTTP، حيث تعرض الرسالة "Python Powered" الشعار:
ما ستتعرَّف عليه
- كيفية كتابة دالة HTTP في السحابة الإلكترونية.
- كيفية كتابة دالة السحابة الإلكترونية HTTP التي تأخذ الوسيطات
- كيفية اختبار دالة HTTP Cloud
- كيفية تشغيل خادم HTTP محلي في Python لتجربة الدالة
- كيفية كتابة دالة HTTP للسحابة الإلكترونية تؤدي إلى عرض صورة
2. الإعداد والمتطلبات
إعداد بيئة ذاتية
- سجِّل الدخول إلى Google Cloud Console وأنشئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.
- اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة أحرف لا تستخدمها Google APIs. ويمكنك تعديلها في أي وقت.
- يكون رقم تعريف المشروع فريدًا في جميع مشاريع Google Cloud وغير قابل للتغيير (لا يمكن تغييره بعد تحديده). تنشئ Cloud Console سلسلة فريدة تلقائيًا. فعادةً لا تهتم بما هو. في معظم الدروس التطبيقية حول الترميز، يجب الإشارة إلى رقم تعريف المشروع (الذي يتم تحديده عادةً على أنّه
PROJECT_ID
). وإذا لم يعجبك رقم التعريف الذي تم إنشاؤه، يمكنك إنشاء رقم تعريف عشوائي آخر. ويمكنك بدلاً من ذلك تجربة طلبك الخاص ومعرفة ما إذا كان متاحًا. ولا يمكن تغييره بعد هذه الخطوة ويبقى طوال مدة المشروع. - لمعلوماتك، هناك قيمة ثالثة، وهي رقم المشروع، الذي تستخدمه بعض واجهات برمجة التطبيقات. اطّلِع على مزيد من المعلومات حول هذه القيم الثلاث في المستندات.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام الموارد/واجهات برمجة التطبيقات في Cloud. لن يؤدي إكمال هذا الدرس التطبيقي حول الترميز إلى فرض أي تكاليف، إن وُجدت. لإيقاف تشغيل الموارد لتجنب تحمُّل الفواتير إلى ما هو أبعد من هذا البرنامج التعليمي، يمكنك حذف الموارد التي أنشأتها أو حذف المشروع. يكون مستخدمو Google Cloud الجدد مؤهَّلون للانضمام إلى برنامج فترة تجريبية مجانية بقيمة 300 دولار أمريكي.
بدء Cloud Shell
يمكنك إدارة Google Cloud عن بُعد من الكمبيوتر المحمول، إلا أنّك ستستخدم في هذا الدرس التطبيقي Cloud Shell، وهي بيئة سطر أوامر يتم تشغيلها في السحابة الإلكترونية.
تفعيل Cloud Shell
- من Cloud Console، انقر على تفعيل Cloud Shell .
إذا كانت هذه هي المرة الأولى التي تبدأ فيها Cloud Shell، ستظهر لك شاشة وسيطة تصف ماهيتها. إذا ظهرت لك شاشة وسيطة، انقر على متابعة.
من المفترَض أن تستغرق عملية إدارة الحسابات والاتصال بخدمة Cloud Shell بضع دقائق فقط.
يتم تحميل هذا الجهاز الافتراضي مع جميع أدوات التطوير اللازمة. وتوفّر هذه الشبكة دليلاً رئيسيًا دائمًا بسعة 5 غيغابايت ويتم تشغيله في Google Cloud، ما يحسّن بشكل كبير من أداء الشبكة والمصادقة. يمكنك تنفيذ معظم عملك، إن لم يكن كلّه، في هذا الدرس التطبيقي حول الترميز باستخدام متصفّح.
بعد الربط بخدمة Cloud Shell، من المفترض أن تتأكّد من أنّه تمّت مصادقتك وأنّ المشروع مضبوط على رقم تعريف مشروعك.
- شغِّل الأمر التالي في Cloud Shell لتأكيد مصادقتك:
gcloud auth list
مخرجات الأمر
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- شغّل الأمر التالي في Cloud Shell للتأكد من معرفة الأمر gcloud بمشروعك:
gcloud config list project
مخرجات الأمر
[core] project = <PROJECT_ID>
إذا لم يكن كذلك، يمكنك تعيينه من خلال هذا الأمر:
gcloud config set project <PROJECT_ID>
مخرجات الأمر
Updated property [core/project].
التأكّد من تفعيل Cloud Functions وCloud Build APIs
شغِّل الأمر التالي من Cloud Shell للتأكّد من تفعيل Cloud Functions وCloud Build APIs:
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
ملاحظة: سيتم استدعاء Cloud Build بواسطة الأمر gcloud functions deploy
وسينشئ تلقائيًا الرمز في صورة حاوية.
تنزيل رمز المصدر
من الوحدة الطرفية Cloud Shell، شغِّل الأوامر التالية:
REPO_NAME="codelabs" REPO_URL="https://github.com/GoogleCloudPlatform/$REPO_NAME" SOURCE_DIR="cloud-functions-python-http" git clone --no-checkout --filter=blob:none --depth=1 $REPO_URL cd $REPO_NAME git sparse-checkout set $SOURCE_DIR git checkout cd $SOURCE_DIR
التحقق من محتوى دليل المصدر:
ls
يجب أن يكون لديك الملفات التالية:
main.py python-powered.png test_main.py web_app.py
3- إضافة دوال HTTP في السحابة الإلكترونية
تتم كتابة دوال HTTP السحابية في لغة بايثون كدوال بايثون عادية. يجب أن تقبل الدالة وسيطة flask.Request
واحدة، والتي تُسمى عادةً request
.
main.py
import flask
def hello_world(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello World! 👋"
"""
response = "Hello World! 👋"
return flask.Response(response, mimetype="text/plain")
# ...
يمكنك فتح الملف باستخدام محرِّر سطر الأوامر المفضَّل لديك (nano أو vim أو emacs). يمكنك أيضًا فتحه في "محرِّر Cloud Shell" بعد ضبط الدليل المصدر كمساحة عمل:
cloudshell open-workspace .
لننشر هذه الدالة كدالة HTTP Cloud باستخدام الأمر gcloud functions deploy
:
FUNCTION_NAME="hello_world" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
مخرجات الأمر:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
ملاحظات حول خيارات gcloud functions deploy
:
--runtime
: تحدد هذه السياسة بيئة التشغيل الخاصة باللغة. بالنسبة إلى بايثون، يمكن أن تكون هذه القيم حاليًاpython37
أوpython38
أوpython39
أوpython310
أوpython312
. راجِع بيئات التشغيل.--trigger-http
: سيتم تعيين نقطة نهاية للدالة. ستؤدي طلبات HTTP (POST وPUT وGET وDELETE وOPTIONS) إلى نقطة النهاية إلى تشغيل تنفيذ الدالة.--allow-unauthenticated
: ستكون الوظيفة متاحة للجميع، ما يسمح لجميع المتصلين بدون التحقّق من المصادقة.- لمزيد من المعلومات، يمكنك الاطّلاع على مقالة نشر دوال gcloud.
لاختبار الدالة، يمكنك النقر على عنوان URL httpsTrigger.url
المعروض في ناتج الأمر أعلاه. يمكنك أيضًا استرداد عنوان URL آليًا واستدعاء الدالة باستخدام الأوامر التالية:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
من المفترض أن تحصل على النتيجة التالية:
Hello World! 👋
4. كتابة دالة السحابة الإلكترونية HTTP التي تأخذ الوسيطات
تكون الدوال أكثر تنوّعًا عند قبول الوسيطات. لنحدِّد دالة جديدة hello_name
تتوافق مع مَعلمة name
:
main.py
# ...
def hello_name(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello {NAME}! 🚀" if "name=NAME" is defined in the GET request
- "Hello World! 🚀" otherwise
"""
name = request.args.get("name", "World")
response = f"Hello {name}! 🚀"
return flask.Response(response, mimetype="text/plain")
# ...
لننشر هذه الدالة الجديدة:
FUNCTION_NAME="hello_name" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
مخرجات الأمر:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
لاختبار الدالة، يمكنك النقر على عنوان URL httpsTrigger.url
المعروض في ناتج الأمر أعلاه. يمكنك أيضًا استرداد عنوان URL آليًا واستدعاء الدالة باستخدام الأوامر التالية:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
من المفترض أن تحصل على النتيجة التلقائية:
Hello World! 🚀
أنت تحصل على النتيجة التلقائية لأنّه لم يتم ضبط الوسيطة name
. إضافة مَعلمة إلى عنوان URL:
curl -w "\n" $URL?name=YOUR%20NAME
هذه المرة، ستحصل على ردك المخصص:
Hello YOUR NAME! 🚀
الخطوة التالية هي إضافة اختبارات الوحدة لضمان استمرار عمل الوظائف على النحو المنشود عند تحديث رمز المصدر.
5- كتابة الاختبارات
يتم اختبار دوال HTTP السحابية في لغة بايثون باستخدام وحدة unittest
من المكتبة العادية. ليست هناك حاجة إلى تشغيل محاكي أو محاكاة أخرى لاختبار الدالة — كل ما عليك هو رمز بايثون عادي.
في ما يلي شكل الاختبار للدالتَين hello_world
وhello_name
:
test_main.py
import unittest
import unittest.mock
import main
class TestHello(unittest.TestCase):
def test_hello_world(self):
request = unittest.mock.Mock()
response = main.hello_world(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 👋"
def test_hello_name_no_name(self):
request = unittest.mock.Mock(args={})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 🚀"
def test_hello_name_with_name(self):
name = "FirstName LastName"
request = unittest.mock.Mock(args={"name": name})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == f"Hello {name}! 🚀"
- تُكتب اختبارات بايثون بالطريقة نفسها التي تُكتب بها ملفات بايثون الأخرى. فهي تبدأ بمجموعة من عمليات الاستيراد، ثم تحدد الفئات والدوال.
- نموذج بيان الاختبار هو
class TestHello(TestCase)
. يجب أن تكون فئة مكتسبة منunittest.TestCase
. - تتضمّن فئة الاختبار طرقاً، يجب أن تبدأ كل منها بـ
test_
، والتي تمثّل حالات الاختبار الفردية. - تختبر كل حالة اختبار إحدى الدوال من خلال محاكاة مَعلمة
request
(أي استبدالها بعنصر مزيّف بالبيانات المحدّدة المطلوبة للاختبار). - بعد استدعاء كل دالة، يتحقق الاختبار من استجابة HTTP للتأكد من أنها هي ما توقعناه.
بما أنّ main.py
يعتمد على flask
، احرص على تثبيت إطار عمل Flask في بيئة الاختبار:
pip install flask
يؤدي تثبيت Flask إلى ظهور نتيجة مشابهة لما يلي:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
إجراء هذه الاختبارات محليًا:
python -m unittest
يجب أن تجتاز اختبارات الوحدات الثلاث ما يلي:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
الخطوة التالية هي إنشاء دالة جديدة تعرض الرمز "Python Powered" الشعار.
6- أو كتابة "مستند Python" دالة HTTP السحابية
لنجعل إحدى الدوال الجديدة أكثر تسلية إلى حدٍ ما من خلال عرض "البيانات المستندة إلى بايثون" صورة لكل طلب:
توضح القائمة التالية الرمز الذي سيتم تنفيذه:
main.py
# ...
def python_powered(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- The official "Python Powered" logo
"""
return flask.send_file("python-powered.png")
تفعيل دالة python_powered
جديدة:
FUNCTION_NAME="python_powered" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
مخرجات الأمر:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
لاختبار الدالة، انقر على عنوان URL httpsTrigger.url
المعروض في ناتج الأمر أعلاه. إذا كان كل شيء يعمل بشكل صحيح، ستظهر لك الرسالة "واجهة Python" شعار في علامة تبويب جديدة داخل المتصفح
بعد ذلك، ستنشئ تطبيقًا لتتمكّن من تشغيل الدالة وتجربتها محليًا قبل النشر.
7. تشغيل الدالة محليًا
يمكنك تشغيل دالة HTTP محليًا عن طريق إنشاء تطبيق ويب واستدعاء الدالة في مسار ما. يمكنك إضافته في نفس الدليل الموجود في الدالة. يتضمّن الملف المُسمّى web_app.py
المحتوى التالي:
web_app.py
import flask
import main
app = flask.Flask(__name__)
@app.get("/")
def index():
return main.python_powered(flask.request)
if __name__ == "__main__":
# Local development only
# Run "python web_app.py" and open http://localhost:8080
app.run(host="localhost", port=8080, debug=True)
- ينشئ هذا الملف تطبيق Flask.
- ويسجِّل مسارًا في عنوان URL الأساسي الذي يتم التعامل معه مع دالة تُسمى
index()
. - بعد ذلك، تستدعي الدالة
index()
الدالةpython_powered
، وتمررها الطلب الحالي.
تأكَّد من تثبيت إطار عمل Flask في بيئة التطوير:
pip install flask
يؤدي تثبيت Flask إلى ظهور نتيجة مشابهة لما يلي:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
لتشغيل هذا التطبيق محليًا، شغِّل الأمر التالي:
python web_app.py
يمكنك الآن استخدام Cloud Shell Web Preview لاختبار تطبيق الويب في المتصفّح. في Cloud Shell، انقر على "معاينة الويب" وحدد "معاينة على المنفذ 8080":
تفتح Cloud Shell عنوان URL للمعاينة على خدمة الخادم الوكيل في نافذة متصفِّح جديدة. تحصر معاينة الويب الدخول عبر HTTPS في حساب المستخدم فقط. إذا كان كل شيء يعمل بشكل صحيح، ينبغي أن ترى "واجهة Python" الشعار!
8. تهانينا!
لقد فعّلت دوال HTTP Cloud باستخدام وظائف اصطلاحية تعالج طلبات الويب من خلال إطار العمل Flask.
يستند أسعار Cloud Functions إلى عدد مرات استدعاء الدالة، بما في ذلك طبقة مجانية للدوال التي لا يتم تشغيلها كثيرًا. بعد الانتهاء من اختبار دوال Cloud، يمكنك حذفها باستخدام gcloud
:
gcloud functions delete hello_world --quiet gcloud functions delete hello_name --quiet gcloud functions delete python_powered --quiet
يمكنك أيضًا حذف الوظائف من وحدة تحكُّم Google Cloud.
نأمل أن تستمتع باستخدام دوال Cloud في بايثون.