0Pricing
Python Academy · درس

مديرو السياق والمكرّرات غير المتزامنين

نفّذ بروتوكولي async with وasync for

مديرو السياق والمكرّرات غير المتزامنين درس مجاني في Python Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Python Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Python Academy 4 دروس في المجموع.

عبارة async with

استخدم async with مع مديري السياق الذين يتضمن إعدادهم أو إنهاؤهم انتظار عمليات إدخال وإخراج. يجب أن يطبّق الكائن المُدار __aenter__ و__aexit__.

import asyncio

class AsyncFile:
    async def __aenter__(self):
        print("open")
        return self
    async def __aexit__(self, *args):
        print("close")

async def main():
    async with AsyncFile() as f:
        print("using")

asyncio.run(main())

__aenter__ و __aexit__

كلاهما coroutine. يُنتظر __aenter__ عند الدخول، ويُنتظر __aexit__ عند الخروج حتى إذا وقع استثناء.

import asyncio

class DBSession:
    async def __aenter__(self):
        self.conn = await async_connect()
        return self.conn

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            await self.conn.rollback()
        else:
            await self.conn.commit()
        await self.conn.close()
        return False

@asynccontextmanager

تتيح لك contextlib.asynccontextmanager كتابة مديري سياق غير متزامنين على هيئة دوال مولِّدات غير متزامنة.

from contextlib import asynccontextmanager
import asyncio

@asynccontextmanager
async def managed_resource():
    print("acquire")
    try:
        yield {"status": "ready"}
    finally:
        print("release")

async def main():
    async with managed_resource() as r:
        print(r["status"])

asyncio.run(main())

عبارة async for

تكرّر async for على iterable غير متزامن، أي كائن يطبّق __aiter__ و__anext__. وقد تتضمن كل دورة عملية إدخال وإخراج.

import asyncio

class AsyncCounter:
    def __init__(self, n): self.n, self.i = n, 0
    def __aiter__(self): return self
    async def __anext__(self):
        if self.i >= self.n: raise StopAsyncIteration
        await asyncio.sleep(0)
        self.i += 1
        return self.i

async def main():
    async for val in AsyncCounter(3):
        print(val)

asyncio.run(main())

المولّدات غير المتزامنة

تكون الدالة async def التي تحتوي على yield مولّدًا غير متزامن. استخدم async for لاستهلاكه.

import asyncio

async def ticker(n):
    for i in range(n):
        await asyncio.sleep(1)
        yield i

async def main():
    async for val in ticker(3):
        print(val)   # 0, 1, 2 with 1-s pauses

asyncio.run(main())

aiofiles لإدخال وإخراج الملفات بشكل غير متزامن

تغلّف مكتبة aiofiles عمليات الملفات داخل مديري سياق غير متزامنين ومكرّرات غير متزامنة.

# pip install aiofiles
import aiofiles, asyncio

async def main():
    async with aiofiles.open("data.txt", "r") as f:
        async for line in f:
            print(line.strip())

جلسة aiohttp للعميل

يُعد aiohttp.ClientSession مدير سياق غير متزامن لإجراء طلبات HTTP متزامنة.

# pip install aiohttp
import aiohttp, asyncio

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.json()

asyncio.run(fetch("https://api.example.com/data"))

مديرو سياق غير متزامنين متعددون

يمكنك ترتيب عدة عبارات async with في سطر واحد، باستخدام الصيغة الموضوعة بين أقواس في Python 3.10 فأحدث.

import asyncio

async def main():
    async with (
        open_db() as db,
        open_cache() as cache,
    ):
        data = await db.fetch("SELECT 1")
        await cache.set("key", data)

AsyncExitStack

يدير contextlib.AsyncExitStack مجموعةً ديناميكيةً من مديري السياق غير المتزامنين.

from contextlib import AsyncExitStack
import asyncio

async def main():
    async with AsyncExitStack() as stack:
        conn1 = await stack.enter_async_context(connect("db1"))
        conn2 = await stack.enter_async_context(connect("db2"))
        await process(conn1, conn2)

اختبار التعليمات البرمجية غير المتزامنة باستخدام pytest-asyncio

تتيح لك pytest-asyncio كتابة دوال اختبار غير متزامنة باستخدام العلامة @pytest.mark.asyncio.

# pip install pytest-asyncio
import pytest, asyncio

async def fetch(): return 42

@pytest.mark.asyncio
async def test_fetch():
    result = await fetch()
    assert result == 42

ملخص بروتوكول المكرّر غير المتزامن

يكون الكائن قابلًا للتكرار بشكل غير متزامن إذا كان يملك __aiter__. ويكون مكرّرًا غير متزامن إذا كان يملك أيضًا __anext__. وتطبّق المولّدات غير المتزامنة كليهما تلقائيًا.

import asyncio

async def gen():
    yield 1
    yield 2

async def main():
    g = gen()
    print(await g.__anext__())   # 1
    print(await g.__anext__())   # 2

تحقق سريع

ما أسلوبا dunder اللذان يجب أن يطبّقهما الكائن لاستخدامه مع async with؟

مراجعة

استخدم async with مع الموارد التي تحتاج إلى إعداد وإنهاء غير متزامنين. واستخدم async for مع المكرّرات التي تنتج القيم بشكل غير متزامن. تُسهّل المولّدات غير المتزامنة إنشاء المكرّرات غير المتزامنة. وتوفّر مكتبات مثل aiofiles وaiohttp عمليات أصلية غير متزامنة للملفات وHTTP.

الأسئلة الشائعة

هل درس «مديرو السياق والمكرّرات غير المتزامنين» مجاني؟

نعم — نص درس «مديرو السياق والمكرّرات غير المتزامنين» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Python Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Python Academy 4 دروس في المجموع.

ماذا ستتعلم في «مديرو السياق والمكرّرات غير المتزامنين»؟

نفّذ بروتوكولي async with وasync for تتمرن على Python Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Python Academy؟

لا تُشترط خبرة سابقة. Python Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «مديرو السياق والمكرّرات غير المتزامنين»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Python Academy هذا؟

نعم. كل درس في Python Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الكوروتينات وحلقة الأحداث
  2. await والمهام والتجميع
  3. مديرو السياق والمكرّرات غير المتزامنين
  4. أنماط الإدخال والإخراج غير المتزامن في بيئة الإنتاج
← العودة إلى Python Academy