CodeGym /Kurslar /Python SELF AZ /Asinxron metodlar

Asinxron metodlar

Python SELF AZ
Səviyyə , Dərs
Mövcuddur

3.1 asyncio modulu

Asinxron alt tapşırıqlar üçün öz thread-lərini yaradıb istifadə edənlər artıq çox azdır. Düzdür, onları yaratmaq olar, amma belə üsullar çox aşağı səviyyəli hesab olunur və yalnız framework yaradıcıları tərəfindən istifadə olunur. O da, başqa cür mümkün olmadıqda.

Hal-hazırda trenddə asinxron proqramlaşdırma, async/await operatorlarıkorutinalar ilə task-lardır. Amma hər şeyi sırayla danışaq…

Bir az tarix

Əvvəllər Python-da asinxron proqramlaşdırma problemlərini həll etmək üçün korutinalar-dan istifadə olunurdu, bunlar generatorlara əsaslanırdı. Daha sonra, Python 3.4-də asyncio (bəzən async IO kimi yazılır) modulu təqdim edildi, hansı ki asinxron proqramlaşdırma mexanizmlərini təqdim edir. Python 3.5-də isə async/await konstruktoru əlavə olundu.

İndi isə bir az giriş məlumatı. Əvvəlcə bu şeylər haqqında qısa danışacağam, sonra daha ətraflı, sonra isə daha da ətraflı. Çünki, demək olar ki, hamısı bir-biri ilə əlaqəli işləyir və bir anlayışın iş prinsipini digərinə istinad etmədən izah etmək mümkün deyil.

asyncio modulu

asyncio modulu asinxron proqramlar yazmaq üçün nəzərdə tutulub, burada tapşırıqları paralel yerinə yetirmək mümkündür. Modul, asinxron I/O əməliyyatlarını, timerləri, socket-ləri, korutina icrasını və çox thread-lərin idarə edilməsini dəstəkləyir, həm bir, həm də bir neçə Event Loop-da işləyə bilir.

Korutinalar (Coroutines)

Korutinalar — bu asinxron funksiyalardır, hansılar ki async def açar sözü ilə təyin olunur. Korutinalar await açar sözü ilə öz icrasını dayandırmaq imkanını verir, bu da digər korutinaların bu vaxt ərzində icrasına imkan verir.


import asyncio

# Asinxron funksiyanın təyini (korutina)
async def main():
    print('Salam ...')
    # 1 saniyəlik icranı dayandırırıq
    await asyncio.sleep(1)
    print('... Dünya!')

# Asinxron funksiyanı Event Loop-da başlatmaq
asyncio.run(main())

Event Loop (Dövr)

Event Loop korutinaların, task-ların və digər asinxron əməliyyatların icrasını idarə edir. asyncio.run() çağrışı dövrü başlatır və korutinaları tamamlamağa qədər icra edir.


import asyncio

async def main():
    print('Salam ...')
    await asyncio.sleep(1)
    print('... Dünya!')

# Hazırkı Event Loop-u əldə edirik
loop = asyncio.get_event_loop()
# Korutinaları tamamlamağa qədər işlədirik
loop.run_until_complete(main())
# Event Loop-dan çıxırıq bütün task-ları tamamlandıqdan sonra
loop.close()

Task-lar (Tasks)

Task-lar korutinaları paralel şəkildə işə salmağa imkan verir. Onlar asyncio.create_task() və ya asyncio.ensure_future() ilə yaradılır.


import asyncio

# Gecikmə ilə işləyəcək korutina təyini
async def say_after(delay, what):
    # İcranı təyin olunan müddətə dayandırırıq
    await asyncio.sleep(delay)
    print(what)

# Əsas korutina
async def main():
    # Korutinaları paralel icra etmək üçün task yaradılır
    task1 = asyncio.create_task(say_after(1, 'salam'))
    task2 = asyncio.create_task(say_after(2, 'dünya'))
    
    # Hər iki task-ın bitməsini gözləyirik
    await task1
    await task2

# Əsas korutina işə düşür
asyncio.run(main())

Future-lər (Futures)

Future obyektləri, gələcəkdə mövcud olacaq asinxron əməliyyatların nəticələrini təmsil edir. Məsələn, asinxron task-ların tamamlanmasını gözləmək üçün istifadə olunur.


import asyncio

# Uzunmüddətli vəzifəni imitasiya edən korutina təyini
async def long_running_task():
    print('Task başladı')
    # 3 saniyəlik icranı dayandırırıq
    await asyncio.sleep(3)
    print('Task bitdi')
    return 'Nəticə'

# Əsas korutina
async def main():
    # Task-in bitməsini gözləyəcək Future yaradılır
    future = asyncio.ensure_future(long_running_task())
    # Task-i bitməsinə qədər gözləyirik və nəticəni alırıq
    result = await future  
    print(f'Task nəticəsi: {result}')

# Əsas korutina işə düşür
asyncio.run(main())

3.2 Asinxron funksiya — async def

Asinxron funksiya adi funksiya kimi elan olunur, sadəcə def açar sözündən əvvəl async yazmaq lazımdır.


async def İsimFunktsiyası(parametrlər):
    funksiyanın kodu

Asinxron funksiya adi funksiya kimi elan olunur, adi funksiya kimi çağırılır, amma nəticəni fərqli qaytarır. Əgər asinxron funksiyanı çağırsanız, o sizə nəticəni yox, xüsusi bir obyekt — korutina qaytaracaq.

Bunu hətta yoxlaya bilərsiniz:


import asyncio

async def main():
    print("Hello World")
            
# Asinxron funksiyanın çağırılması, bu korutina qaytarır
result = main()
# Nəticənin tipini yoxlayırıq
print(type(result)) # <class 'coroutine'>

Nə baş verir? Əgər funksiyanı async sözü ilə işarələsəniz, əslində ona bir dekorator əlavə etmiş olursunuz ki, bu təxminən belə işləyir:


def async_decorator(func):
    # Task obyektini yaradırıq
    task = Task()
    # Bizim func funksiyamızı onun hədəfi olaraq təyin edirik ki, icra etsin
    task.target = func  
    # Task obyektini Tapşırıqlar növbəsinə daxil edirik — Event Loop
    eventloop.add_task(task)  
    # Task obyektini qaytarırıq
    return task 

Kodunuz bu hala gəlir:


import asyncio

@async_decorator
def main():
    print("Hello World")
            
result = main()
print(type(result)) # <class 'coroutine'>

Bu analoqun mənası budur:

Asinxron funksiyanı çağırdığınız zaman xüsusi bir Task obyekti yaradılır ki, sizin funksiyanızı yerinə yetirəcək, amma nə vaxtsa, gələcəkdə. Bəlkə 0.0001 saniyədən sonra, bəlkə də 10 saniyədən sonra.

Bu task obyekti (korutina) sizə dərhal asinxron funksiyanızın çağırılmasının nəticəsi kimi qaytarılır.

Bu korutina olur. Ola bilsin ki, sizin asinxron funksiyanız hələ yerinə yetirilməyə başlamayıb, amma task obyekti (korutina) artıq sizdə var.

Niyə sizə bu task (korutina) lazımdır? Onunla az şey edə bilərsiniz, amma 3 şeyi etmək mümkündür:

  • Asinxron funksiya yerinə yetirilənə kimi gözləmək.
  • Asinxron funksiya yerinə yetiriləndən sonra korutinadan funksiyanın nəticəsini almaq.
  • 10 (istənilən sayda) asinxron funksiyaların yerinə yetirilməsini gözləmək.

Necə olduğunu aşağıda izah edəcəm.

3.3 await operatoru

Korutin ilə bağlı əksər əməliyyatlar "asinxron funksiyanın yerinə yetirilməsini gözləməklə" başlayır. Buna görə də, bu əməliyyat üçün xüsusi bir await operatoru var.

Sizin etməli olduğunuz tək şey onu korutinin qarşısında yazmaqdır:


await korutin

Və ya birbaşa asinxron funksiyanın çağırışının qarşısında:


await asinxron_funksiya(argumentlər)

Python kodda await operatoruna rast gəldikdə, cari funksiyanın icrasını dayandırır və gözləyir ki, korutin icra olunsun — yəni korutinin istinad etdiyi asinxron funksiya tamamlanana qədər.

Vacibdir! await operatoru yalnız asinxron funksiya daxilində istifadə olunur ki, icra dayandırılsın və digər korutin və ya asinxron əməliyyat tamamlanana qədər gözlənsin.

Bu, asinxron funksiyaların çağırışları arasında keçidi sadələşdirmək üçün edilir. Belə bir await çağırışı, əslində "nə qədər gözləyəcəyimizi bilmirik — digər asinxron funksiyaları icra etməkdə davam edin" deyən bir bəyanatdır.

Nümunə:


import asyncio

# Asinxron funksiyanın təyin olunması
async def async_print(text):
    print(text)
        
# Əsas asinxron funksiya
async def main():
    # Asinxron funksiyanın icrasını gözləmək üçün await istifadə olunur
    await async_print("Salam Dünya")
        
# Hadisələr dövrünün işə salınması və main() korutinin icrası
asyncio.run(main()) #asinxron funksiyanı işə salır

Əslində await operatoru daha incə işləyir — o, həmçinin çağırıldığı asinxron funksiyanın icra nəticəsini qaytarır.

Nümunə:


import asyncio

# İki ədədin cəmini hesablayan asinxron funksiyanın təyin olunması
async def async_add(a, b):
    return a + b
        
# Əsas asinxron funksiya
async def main():
    # async_add funksiyasının icra nəticəsini almaq üçün await istifadə olunur
    sum = await async_add(100, 200)
    print(sum)
        
# Hadisələr dövrünün işə salınması və main() korutinin icrası
asyncio.run(main()) #asinxron funksiyanı işə salır

Gəlin yekunlaşdıraq, await operatoru:

  • Cari asinxron funksiyanın, digər korutin və ya asinxron əməliyyat tamamlanana qədər icrasını dayandırır.
  • Asinxron əməliyyatın və ya korutinin icra nəticəsini qaytarır.
  • Yalnız asinxron funksiya daxilində istifadə edilə bilər.
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION