પાયથોનના asyncio ફ્યુચર્સમાં નિપુણતા મેળવો. લો-લેવલ અસુમેળ ખ્યાલો, વ્યવહારુ ઉદાહરણો અને મજબૂત, ઉચ્ચ-પ્રદર્શન એપ્લિકેશન્સ બનાવવા માટેની અદ્યતન તકનીકોનું અન્વેષણ કરો.
Asyncio ફ્યુચર્સ અનલોક કર્યા: પાયથોનમાં લો-લેવલ અસુમેળ પ્રોગ્રામિંગમાં ઊંડાણપૂર્વકનું સંશોધન
આધુનિક પાયથોન ડેવલપમેન્ટની દુનિયામાં, async/await
સિન્ટેક્સ ઉચ્ચ-પ્રદર્શન, I/O-બાઉન્ડ એપ્લિકેશન્સ બનાવવા માટે એક મુખ્ય આધારસ્તંભ બની ગયું છે. તે સમવર્તી કોડ લખવાની એક સ્વચ્છ, ભવ્ય રીત પ્રદાન કરે છે જે લગભગ સિક્વન્શિયલ લાગે છે. પરંતુ આ ઉચ્ચ-સ્તરના સિન્ટેક્ટિક શુગરની નીચે એક શક્તિશાળી અને મૂળભૂત મિકેનિઝમ છુપાયેલું છે: Asyncio ફ્યુચર. જોકે તમે દરરોજ રો Futures સાથે ઇન્ટરેક્ટ ન કરી શકો, તેમ છતાં તેમને સમજવું એ પાયથોનમાં અસુમેળ પ્રોગ્રામિંગમાં સાચી નિપુણતા મેળવવાની ચાવી છે. તે કારના એન્જિન કેવી રીતે કામ કરે છે તે શીખવા જેવું છે; તમારે ડ્રાઇવ કરવા માટે તેને જાણવાની જરૂર નથી, પરંતુ જો તમે માસ્ટર મિકેનિક બનવા માંગતા હો તો તે અનિવાર્ય છે.
આ વ્યાપક માર્ગદર્શિકા asyncio
પરથી પડદો ઉંચકશે. આપણે એક્સપ્લોર કરીશું કે ફ્યુચર્સ શું છે, તેઓ કોરોટિન્સ અને ટાસ્કથી કેવી રીતે અલગ છે, અને શા માટે આ લો-લેવલ પ્રિમિટિવ પાયથોનની અસુમેળ ક્ષમતાઓનો આધારસ્તંભ છે. પછી ભલે તમે જટિલ રેસ કન્ડિશનને ડીબગ કરી રહ્યા હો, જૂની કોલબેક-આધારિત લાઇબ્રેરીઓ સાથે એકીકૃત કરી રહ્યા હો, અથવા ફક્ત અસુમેળની ઊંડી સમજણ મેળવવા માંગતા હો, આ લેખ તમારા માટે છે.
Asyncio ફ્યુચર બરાબર શું છે?
મૂળભૂત રીતે, asyncio.Future
એ એક ઑબ્જેક્ટ છે જે અસુમેળ ઑપરેશનના અંતિમ પરિણામનું પ્રતિનિધિત્વ કરે છે. તેને એક પ્લેસહોલ્ડર, એક વચન, અથવા એવા મૂલ્ય માટેની રસીદ તરીકે વિચારો જે હજી ઉપલબ્ધ નથી. જ્યારે તમે કોઈ ઑપરેશન શરૂ કરો છો જેને પૂર્ણ થવામાં સમય લાગશે (જેમ કે નેટવર્ક વિનંતી અથવા ડેટાબેઝ ક્વેરી), ત્યારે તમે તરત જ ફ્યુચર ઑબ્જેક્ટ પાછું મેળવી શકો છો. તમારો પ્રોગ્રામ અન્ય કાર્ય કરવાનું ચાલુ રાખી શકે છે, અને જ્યારે ઑપરેશન આખરે પૂર્ણ થાય છે, ત્યારે પરિણામ (અથવા ભૂલ) તે ફ્યુચર ઑબ્જેક્ટની અંદર મૂકવામાં આવશે.
એક મદદરૂપ વાસ્તવિક-દુનિયાનું ઉદાહરણ વ્યસ્ત કેફેમાં કોફીનો ઑર્ડર આપવા જેવું છે. તમે તમારો ઑર્ડર આપો અને ચૂકવણી કરો છો, અને બરિસ્ટા તમને ઑર્ડર નંબર સાથેની રસીદ આપે છે. તમારી પાસે હજી તમારી કોફી નથી, પરંતુ તમારી પાસે રસીદ છે—કોફીનું વચન. તમે હવે કાઉન્ટર પર નિષ્ક્રિય ઊભા રહેવાને બદલે ટેબલ શોધવા અથવા તમારો ફોન તપાસવા જઈ શકો છો. જ્યારે તમારી કોફી તૈયાર થાય છે, ત્યારે તમારો નંબર બોલાવવામાં આવે છે, અને તમે અંતિમ પરિણામ માટે તમારી રસીદને 'રીડીમ' કરી શકો છો. રસીદ એ ફ્યુચર છે.
ફ્યુચરની મુખ્ય લાક્ષણિકતાઓ આ પ્રમાણે છે:
- લો-લેવલ: ટાસ્ક (કાર્ય) ની સરખામણીમાં ફ્યુચર્સ વધુ પ્રિમિટિવ બિલ્ડિંગ બ્લોક છે. તેઓ આંતરિક રીતે કોઈ કોડ કેવી રીતે ચલાવવો તે જાણતા નથી; તેઓ ફક્ત એવા પરિણામ માટેના કન્ટેનર છે જે પછીથી સેટ કરવામાં આવશે.
- અવેઇટેબલ: ફ્યુચરની સૌથી મહત્વપૂર્ણ વિશેષતા એ છે કે તે એક અવેઇટેબલ ઑબ્જેક્ટ છે. આનો અર્થ એ છે કે તમે તેના પર
await
કીવર્ડનો ઉપયોગ કરી શકો છો, જે ફ્યુચર પાસે પરિણામ ન હોય ત્યાં સુધી તમારા કોરોટિનના એક્ઝિક્યુશનને થોભાવશે. - સ્ટેટફુલ: ફ્યુચર તેના જીવનચક્ર દરમિયાન કેટલીક અલગ-અલગ સ્થિતિઓમાંથી એકમાં અસ્તિત્વ ધરાવે છે: પેન્ડિંગ, કેન્સલ, અથવા ફિનિશ્ડ.
ફ્યુચર્સ વિ. કોરોટિન્સ વિ. ટાસ્ક: મૂંઝવણ દૂર કરવી
asyncio
માટે નવા ડેવલપર્સ માટે સૌથી મોટા અવરોધો પૈકી એક આ ત્રણ મુખ્ય ખ્યાલો વચ્ચેના સંબંધને સમજવાનો છે. તેઓ ઊંડાણપૂર્વક એકબીજા સાથે જોડાયેલા છે પરંતુ વિવિધ હેતુઓ પૂરા પાડે છે.
1. કોરોટિન્સ
કોરોટિન એ ફક્ત async def
સાથે વ્યાખ્યાયિત થયેલું એક ફંક્શન છે. જ્યારે તમે કોરોટિન ફંક્શનને કૉલ કરો છો, ત્યારે તે તેનો કોડ એક્ઝિક્યુટ કરતું નથી. તેના બદલે, તે એક કોરોટિન ઑબ્જેક્ટ પરત કરે છે. આ ઑબ્જેક્ટ કમ્પ્યુટેશન માટેની બ્લુપ્રિન્ટ છે, પરંતુ ઇવેન્ટ લૂપ દ્વારા તેને ચલાવવામાં ન આવે ત્યાં સુધી કંઈ થતું નથી.
ઉદાહરણ:
async def fetch_data(url): ...
Calling fetch_data("http://example.com")
gives you a coroutine object. It's inert until you await
it or schedule it as a Task.
2. ટાસ્ક (કાર્ય)
asyncio.Task
એ છે જેનો ઉપયોગ તમે ઇવેન્ટ લૂપ પર કોરોટિનને સમવર્તી રીતે ચલાવવા માટે શેડ્યૂલ કરવા માટે કરો છો. તમે asyncio.create_task(my_coroutine())
નો ઉપયોગ કરીને ટાસ્ક બનાવો છો. એક ટાસ્ક તમારા કોરોટિનને લપેટે છે અને ઇવેન્ટ લૂપને તક મળતાની સાથે જ તેને "બેકગ્રાઉન્ડમાં" ચલાવવા માટે તરત જ શેડ્યૂલ કરે છે. અહીં સમજવાની મહત્વની બાબત એ છે કે એક ટાસ્ક એ ફ્યુચરનો સબક્લાસ છે. તે એક વિશિષ્ટ ફ્યુચર છે જે કોરોટિનને કેવી રીતે ચલાવવું તે જાણે છે.
જ્યારે રેપ કરેલ કોરોટિન પૂર્ણ થાય છે અને મૂલ્ય પરત કરે છે, ત્યારે ટાસ્ક (જે, યાદ રાખો, એક ફ્યુચર છે) આપમેળે તેનું પરિણામ સેટ કરે છે. જો કોરોટિન કોઈ અપવાદ ઉભો કરે છે, તો ટાસ્કનો અપવાદ સેટ થાય છે.
3. ફ્યુચર્સ
એક સાદું asyncio.Future
તો વધુ મૂળભૂત છે. ટાસ્કથી વિપરીત, તે કોઈ ચોક્કસ કોરોટિન સાથે બંધાયેલું નથી. તે ફક્ત એક ખાલી પ્લેસહોલ્ડર છે. બીજું કંઈક — તમારા કોડનો બીજો ભાગ, એક લાઇબ્રેરી, અથવા ઇવેન્ટ લૂપ પોતે — તેના પરિણામ અથવા અપવાદને પછીથી સ્પષ્ટપણે સેટ કરવા માટે જવાબદાર છે. ટાસ્ક તમારા માટે આ પ્રક્રિયાને આપમેળે મેનેજ કરે છે, પરંતુ રો ફ્યુચર સાથે, મેનેજમેન્ટ મેન્યુઅલ હોય છે.
અહીં તફાવતને સ્પષ્ટ કરવા માટે એક સારાંશ કોષ્ટક આપેલું છે:
ખ્યાલ | તે શું છે | તે કેવી રીતે બનાવવામાં આવે છે | પ્રાથમિક ઉપયોગ કેસ |
---|---|---|---|
કોરોટિન | async def સાથે વ્યાખ્યાયિત થયેલું ફંક્શન; જનરેટર-આધારિત કમ્પ્યુટેશન બ્લુપ્રિન્ટ. |
async def my_func(): ... |
અસુમેળ લોજિક વ્યાખ્યાયિત કરવું. |
ટાસ્ક | એક ફ્યુચર સબક્લાસ જે ઇવેન્ટ લૂપ પર કોરોટિનને લપેટે છે અને ચલાવે છે. | asyncio.create_task(my_func()) |
કોરોટિન્સને સમવર્તી રીતે ચલાવવું ("ફાયર એન્ડ ફોરગેટ"). |
ફ્યુચર | એક લો-લેવલ અવેઇટેબલ ઑબ્જેક્ટ જે અંતિમ પરિણામનું પ્રતિનિધિત્વ કરે છે. | loop.create_future() |
કોલબેક-આધારિત કોડ સાથે ઇન્ટરફેસિંગ; કસ્ટમ સિંક્રોનાઇઝેશન. |
ટૂંકમાં: તમે કોરોટિન્સ લખો છો. તમે તેમને ટાસ્ક નો ઉપયોગ કરીને સમવર્તી રીતે ચલાવો છો. ટાસ્ક અને અંતર્ગત I/O ઑપરેશન્સ બંને પૂર્ણતાનો સંકેત આપવા માટે ફ્યુચર્સ નો મૂળભૂત મિકેનિઝમ તરીકે ઉપયોગ કરે છે.
ફ્યુચરનું જીવનચક્ર
એક ફ્યુચર રાજ્યોના એક સરળ પરંતુ મહત્વપૂર્ણ સમૂહમાંથી પસાર થાય છે. આ જીવનચક્રને સમજવું એ તેનો અસરકારક રીતે ઉપયોગ કરવા માટેની ચાવી છે.
સ્થિતિ 1: પેન્ડિંગ (બાકી)
જ્યારે ફ્યુચર પ્રથમ બનાવવામાં આવે છે, ત્યારે તે પેન્ડિંગ સ્થિતિમાં હોય છે. તેમાં કોઈ પરિણામ નથી અને કોઈ અપવાદ નથી. તે કોઈની દ્વારા તેને પૂર્ણ થવાની રાહ જોઈ રહ્યું છે.
import asyncio
async def main():
# Get the current event loop
loop = asyncio.get_running_loop()
# Create a new Future
my_future = loop.create_future()
print(f"Is the future done? {my_future.done()}") # Output: False
# To run the main coroutine
asyncio.run(main())
સ્થિતિ 2: સમાપ્તિ (પરિણામ અથવા અપવાદ સેટ કરવો)
એક પેન્ડિંગ ફ્યુચર બેમાંથી એક રીતે પૂર્ણ થઈ શકે છે. આ સામાન્ય રીતે પરિણામના "પ્રોડ્યુસર" દ્વારા કરવામાં આવે છે.
1. set_result()
સાથે સફળ પરિણામ સેટ કરવું:
જ્યારે અસુમેળ ઑપરેશન સફળતાપૂર્વક પૂર્ણ થાય છે, ત્યારે તેનું પરિણામ આ પદ્ધતિનો ઉપયોગ કરીને ફ્યુચર સાથે જોડવામાં આવે છે. આ ફ્યુચરને ફિનિશ્ડ સ્થિતિમાં રૂપાંતરિત કરે છે.
2. set_exception()
સાથે અપવાદ સેટ કરવો:
જો ઑપરેશન નિષ્ફળ જાય, તો અપવાદ ઑબ્જેક્ટ ફ્યુચર સાથે જોડવામાં આવે છે. આ પણ ફ્યુચરને ફિનિશ્ડ સ્થિતિમાં રૂપાંતરિત કરે છે. જ્યારે અન્ય કોરોટિન `await`s this Future, the attached exception will be raised.
સ્થિતિ 3: સમાપ્ત
એકવાર પરિણામ અથવા અપવાદ સેટ થઈ જાય, પછી ફ્યુચર પૂર્ણ ગણાય છે. તેની સ્થિતિ હવે અંતિમ છે અને તેને બદલી શકાતી નથી. તમે future.done()
પદ્ધતિ વડે આ ચકાસી શકો છો. કોઈપણ કોરોટિન્સ જે આ ફ્યુચરને await
કરી રહ્યા હતા તે હવે જાગી જશે અને તેમનું એક્ઝિક્યુશન ફરી શરૂ કરશે.
(વૈકલ્પિક) સ્થિતિ 4: રદ થયેલ
એક પેન્ડિંગ ફ્યુચરને future.cancel()
પદ્ધતિને કૉલ કરીને પણ રદ કરી શકાય છે. આ ઑપરેશન છોડી દેવાની વિનંતી છે. જો રદીકરણ સફળ થાય, તો ફ્યુચર કેન્સલ સ્થિતિમાં પ્રવેશે છે. જ્યારે અવેઇટ કરવામાં આવે છે, ત્યારે રદ થયેલ ફ્યુચર CancelledError
ઉભો કરશે.
ફ્યુચર્સ સાથે કામ કરવું: વ્યવહારુ ઉદાહરણો
સિદ્ધાંત મહત્વપૂર્ણ છે, પરંતુ કોડ તેને વાસ્તવિક બનાવે છે. ચાલો જોઈએ કે તમે ચોક્કસ સમસ્યાઓ હલ કરવા માટે રો ફ્યુચર્સનો ઉપયોગ કેવી રીતે કરી શકો છો.
ઉદાહરણ 1: મેન્યુઅલ પ્રોડ્યુસર/કન્ઝ્યુમર સિનારિયો
આ એક ક્લાસિક ઉદાહરણ છે જે મુખ્ય કોમ્યુનિકેશન પેટર્નને દર્શાવે છે. અમારી પાસે એક કોરોટિન (`consumer`) હશે જે ફ્યુચર પર રાહ જોશે, અને બીજું (`producer`) હશે જે કંઈક કાર્ય કરશે અને પછી તે ફ્યુચર પર પરિણામ સેટ કરશે.
import asyncio
import time
async def producer(future):
print("Producer: Starting to work on a heavy calculation...")
await asyncio.sleep(2) # Simulate I/O or CPU-intensive work
result = 42
print(f"Producer: Calculation finished. Setting result: {result}")
future.set_result(result)
async def consumer(future):
print("Consumer: Waiting for the result...")
# The 'await' keyword pauses the consumer here until the future is done
result = await future
print(f"Consumer: Got the result! It's {result}")
async def main():
loop = asyncio.get_running_loop()
my_future = loop.create_future()
# Schedule the producer to run in the background
# It will work on completing my_future
asyncio.create_task(producer(my_future))
# The consumer will wait for the producer to finish via the future
await consumer(my_future)
asyncio.run(main())
# Expected Output:
# Consumer: Waiting for the result...
# Producer: Starting to work on a heavy calculation...
# (2-second pause)
# Producer: Calculation finished. Setting result: 42
# Consumer: Got the result! It's 42
આ ઉદાહરણમાં, ફ્યુચર સિંક્રોનાઇઝેશન પોઈન્ટ તરીકે કાર્ય કરે છે. The `consumer` doesn't know or care who provides the result; it only cares about the Future itself. This decouples the producer and consumer, which is a very powerful pattern in concurrent systems.
ઉદાહરણ 2: કોલબેક-આધારિત API ને જોડવું
આ રો ફ્યુચર્સ માટેના સૌથી શક્તિશાળી અને સામાન્ય ઉપયોગના કેસો પૈકી એક છે. ઘણી જૂની લાઇબ્રેરીઓ (અથવા C/C++ સાથે ઇન્ટરફેસ કરવાની જરૂર હોય તેવી લાઇબ્રેરીઓ) async/await
નેટિવ નથી. તેના બદલે, તેઓ કોલબેક-આધારિત શૈલીનો ઉપયોગ કરે છે, જ્યાં તમે પૂર્ણ થવા પર એક્ઝિક્યુટ કરવા માટે એક ફંક્શન પાસ કરો છો.
ફ્યુચર્સ આ API ને આધુનિક બનાવવા માટે એક સંપૂર્ણ બ્રિજ પ્રદાન કરે છે. આપણે એક રેપર ફંક્શન બનાવી શકીએ છીએ જે અવેઇટેબલ ફ્યુચર પરત કરે છે.
ચાલો કલ્પના કરીએ કે આપણી પાસે એક કાલ્પનિક લેગસી ફંક્શન legacy_fetch(url, callback)
છે જે URL ને ફેચ કરે છે અને પૂર્ણ થવા પર `callback(data)` ને કૉલ કરે છે.
import asyncio
from threading import Timer
# --- This is our hypothetical legacy library ---
def legacy_fetch(url, callback):
# This function is not async and uses callbacks.
# We simulate a network delay using a timer from the threading module.
print(f"[Legacy] Fetching {url}... (This is a blocking-style call)")
def on_done():
data = f"Some data from {url}"
callback(data)
# Simulate a 2-second network call
Timer(2, on_done).start()
# -----------------------------------------------
async def modern_fetch(url):
"""Our awaitable wrapper around the legacy function."""
loop = asyncio.get_running_loop()
future = loop.create_future()
def on_fetch_complete(data):
# This callback will be executed in a different thread.
# To safely set the result on the future belonging to the main event loop,
# we use loop.call_soon_threadsafe.
loop.call_soon_threadsafe(future.set_result, data)
# Call the legacy function with our special callback
legacy_fetch(url, on_fetch_complete)
# Await the future, which will be completed by our callback
return await future
async def main():
print("Starting modern fetch...")
data = await modern_fetch("http://example.com")
print(f"Modern fetch complete. Received: '{data}'")
asyncio.run(main())
આ પેટર્ન અતિ ઉપયોગી છે. The `modern_fetch` function hides all the callback complexity. From the perspective of `main`, it's just a regular `async` function that can be awaited. We have successfully "futurized" a legacy API.
નોંધ: loop.call_soon_threadsafe
નો ઉપયોગ ત્યારે મહત્વપૂર્ણ છે જ્યારે કોલબેક એક અલગ થ્રેડ દ્વારા એક્ઝિક્યુટ થાય છે, જે asyncio સાથે એકીકૃત ન હોય તેવી લાઇબ્રેરીઓમાં I/O ઑપરેશન્સ સાથે સામાન્ય છે. તે સુનિશ્ચિત કરે છે કે future.set_result
asyncio ઇવેન્ટ લૂપના સંદર્ભમાં સુરક્ષિત રીતે કૉલ થાય છે.
રો ફ્યુચર્સનો ક્યારે ઉપયોગ કરવો (અને ક્યારે નહીં)
ઉપલબ્ધ શક્તિશાળી ઉચ્ચ-સ્તરના એબ્સ્ટ્રેક્શન્સ સાથે, ફ્યુચર જેવા લો-લેવલ ટૂલ માટે ક્યારે પહોંચવું તે જાણવું મહત્વપૂર્ણ છે.
રો ફ્યુચર્સનો ઉપયોગ ત્યારે કરો જ્યારે:
- કોલબેક-આધારિત કોડ સાથે ઇન્ટરફેસિંગ: ઉપરના ઉદાહરણમાં દર્શાવ્યા મુજબ, આ પ્રાથમિક ઉપયોગ કેસ છે. ફ્યુચર્સ આદર્શ બ્રિજ છે.
- કસ્ટમ સિંક્રોનાઇઝેશન પ્રિમિટિવ્સ બનાવી રહ્યા હો: જો તમારે Event, Lock, અથવા Queue નું પોતાનું વર્ઝન ચોક્કસ વર્તણૂકો સાથે બનાવવાની જરૂર હોય, તો ફ્યુચર્સ એ મુખ્ય ઘટક હશે જેના પર તમે નિર્માણ કરશો.
- કોરોટિન સિવાય અન્ય કોઈ વસ્તુ દ્વારા પરિણામ ઉત્પન્ન થાય છે: જો પરિણામ બાહ્ય ઇવેન્ટ સ્રોત દ્વારા ઉત્પન્ન થાય છે (દા.ત., અન્ય પ્રક્રિયામાંથી સિગ્નલ, વેબસોકેટ ક્લાયંટમાંથી સંદેશ), તો ફ્યુચર એ asyncio વિશ્વમાં તે પેન્ડિંગ ઇવેન્ટનું પ્રતિનિધિત્વ કરવાનો સંપૂર્ણ માર્ગ છે.
રો ફ્યુચર્સ ટાળો (તેના બદલે ટાસ્કનો ઉપયોગ કરો) ત્યારે જ્યારે:
- તમે ફક્ત એક કોરોટિનને સમવર્તી રીતે ચલાવવા માંગો છો: આ
asyncio.create_task()
નું કાર્ય છે. તે કોરોટિનને રેપિંગ, તેને શેડ્યૂલ કરવા અને તેના પરિણામ અથવા અપવાદને ટાસ્ક (જે એક ફ્યુચર છે) માં પ્રસારિત કરવાનું સંભાળે છે. અહીં રો ફ્યુચરનો ઉપયોગ કરવો એ વ્હીલને ફરીથી શોધવા જેવું હશે. - સમવર્તી ઑપરેશન્સના જૂથોનું સંચાલન કરવું: બહુવિધ કોરોટિન્સ ચલાવવા અને તેમને પૂર્ણ થવાની રાહ જોવા માટે,
asyncio.gather()
,asyncio.wait()
, અનેasyncio.as_completed()
જેવા ઉચ્ચ-સ્તરના API ઘણા સુરક્ષિત, વધુ વાંચી શકાય તેવા અને ઓછી ભૂલ-પ્રવૃત્તિવાળા છે. આ ફંક્શન્સ સીધા કોરોટિન્સ અને ટાસ્ક પર કાર્ય કરે છે.
અદ્યતન ખ્યાલો અને મુશ્કેલીઓ
ફ્યુચર્સ અને ઇવેન્ટ લૂપ
એક ફ્યુચર જે ઇવેન્ટ લૂપમાં બનાવવામાં આવ્યું હતું તેની સાથે આંતરિક રીતે જોડાયેલું છે. એક `await future` અભિવ્યક્તિ કાર્ય કરે છે કારણ કે ઇવેન્ટ લૂપ આ ચોક્કસ ફ્યુચર વિશે જાણે છે. તે સમજે છે કે જ્યારે તે પેન્ડિંગ ફ્યુચર પર `await` જુએ છે, ત્યારે તેણે વર્તમાન કોરોટિનને સસ્પેન્ડ કરવું જોઈએ અને કરવા માટે અન્ય કાર્ય શોધવું જોઈએ. જ્યારે ફ્યુચર આખરે પૂર્ણ થાય છે, ત્યારે ઇવેન્ટ લૂપ જાણે છે કે કયા સસ્પેન્ડ કરેલા કોરોટિનને જગાડવું.
આથી તમારે હંમેશા loop.create_future()
નો ઉપયોગ કરીને ફ્યુચર બનાવવું જોઈએ, જ્યાં loop
એ હાલમાં ચાલતું ઇવેન્ટ લૂપ છે. વિવિધ ઇવેન્ટ લૂપ (અથવા યોગ્ય સિંક્રોનાઇઝેશન વિનાના વિવિધ થ્રેડ્સ) માં ફ્યુચર્સ બનાવવા અને તેનો ઉપયોગ કરવાનો પ્રયાસ કરવાથી ભૂલો અને અણધારી વર્તણૂક થશે.
`await` ખરેખર શું કરે છે
જ્યારે પાયથોન ઇન્ટરપ્રિટર result = await my_future
નો સામનો કરે છે, ત્યારે તે અંદરથી કેટલાક પગલાં ભરે છે:
- તે
my_future.__await__()
ને કૉલ કરે છે, જે એક ઇટરેટર પરત કરે છે. - તે તપાસે છે કે ફ્યુચર પહેલેથી જ પૂર્ણ થયું છે કે નહીં. જો એમ હોય, તો તે પરિણામ મેળવે છે (અથવા અપવાદ ઉભો કરે છે) અને સસ્પેન્ડ કર્યા વિના ચાલુ રહે છે.
- જો ફ્યુચર પેન્ડિંગ હોય, તો તે ઇવેન્ટ લૂપને કહે છે: "મારા એક્ઝિક્યુશનને સસ્પેન્ડ કરો, અને કૃપા કરીને જ્યારે આ ચોક્કસ ફ્યુચર પૂર્ણ થાય ત્યારે મને જગાડો."
- ઇવેન્ટ લૂપ પછી કાર્યભાર સંભાળે છે, અન્ય તૈયાર ટાસ્ક ચલાવે છે.
- એકવાર
my_future.set_result()
અથવાmy_future.set_exception()
ને કૉલ કરવામાં આવે, પછી ઇવેન્ટ લૂપ ફ્યુચરને પૂર્ણ તરીકે ચિહ્નિત કરે છે અને લૂપના આગામી પુનરાવર્તન પર સસ્પેન્ડ કરેલા કોરોટિનને ફરી શરૂ કરવા માટે શેડ્યૂલ કરે છે.
સામાન્ય મુશ્કેલી: ફ્યુચર્સને ટાસ્ક સાથે ગૂંચવવું
એક સામાન્ય ભૂલ એ છે કે જ્યારે ટાસ્ક યોગ્ય સાધન હોય ત્યારે ફ્યુચર સાથે કોરોટિનના એક્ઝિક્યુશનને મેન્યુઅલી મેનેજ કરવાનો પ્રયાસ કરવો.
ખોટો માર્ગ (અતિશય જટિલ):
# This is verbose and unnecessary
async def main_wrong():
loop = asyncio.get_running_loop()
future = loop.create_future()
# A separate coroutine to run our target and set the future
async def runner():
try:
result = await some_other_coro()
future.set_result(result)
except Exception as e:
future.set_exception(e)
# We have to manually schedule this runner coroutine
asyncio.create_task(runner())
# Finally, we can await our future
final_result = await future
સાચો માર્ગ (ટાસ્કનો ઉપયોગ કરીને):
# A Task does all of the above for you!
async def main_right():
# A Task is a Future that automatically drives a coroutine
task = asyncio.create_task(some_other_coro())
# We can await the task directly
final_result = await task
Task
એ Future
નો સબક્લાસ હોવાથી, બીજું ઉદાહરણ માત્ર વધુ સ્વચ્છ નથી પરંતુ કાર્યાત્મક રીતે સમકક્ષ અને વધુ કાર્યક્ષમ પણ છે.
નિષ્કર્ષ: Asyncio નો પાયો
Asyncio ફ્યુચર એ પાયથોનના અસુમેળ ઇકોસિસ્ટમનો અદ્રશ્ય હીરો છે. તે લો-લેવલ પ્રિમિટિવ છે જે async/await
ના ઉચ્ચ-સ્તરના જાદુને શક્ય બનાવે છે. જ્યારે તમારું દૈનિક કોડિંગ મુખ્યત્વે કોરોટિન્સ લખવા અને તેમને ટાસ્ક તરીકે શેડ્યૂલ કરવા સાથે સંકળાયેલું હશે, ત્યારે ફ્યુચર્સને સમજવું તમને બધું કેવી રીતે જોડાયેલું છે તેની ઊંડી સમજ આપે છે.
ફ્યુચર્સમાં નિપુણતા મેળવીને, તમે આ ક્ષમતાઓ પ્રાપ્ત કરો છો:
- આત્મવિશ્વાસ સાથે ડીબગ કરવું: જ્યારે તમે
CancelledError
અથવા ક્યારેય પરત ન ફરતું કોરોટિન જુઓ છો, ત્યારે તમે અંતર્ગત ફ્યુચર અથવા ટાસ્કની સ્થિતિ સમજી શકશો. - કોઈપણ કોડને એકીકૃત કરવો: હવે તમારી પાસે કોઈપણ કોલબેક-આધારિત API ને રેપ કરવાની અને તેને આધુનિક અસુમેળ વિશ્વમાં પ્રથમ-વર્ગના નાગરિક બનાવવાની શક્તિ છે.
- અદ્યતન ટૂલ્સ બનાવવું: ફ્યુચર્સનું જ્ઞાન તમારા પોતાના અદ્યતન સમવર્તી અને સમાંતર પ્રોગ્રામિંગ કન્સ્ટ્રક્ટ્સ બનાવવા તરફનું પ્રથમ પગલું છે.
તો, આગલી વખતે જ્યારે તમે asyncio.create_task()
અથવા await asyncio.gather()
નો ઉપયોગ કરો છો, ત્યારે પડદા પાછળ અથાક કામ કરતા સાધારણ ફ્યુચરની પ્રશંસા કરવા માટે થોડો સમય કાઢો. તે મજબૂત, સ્કેલેબલ અને ભવ્ય અસુમેળ પાયથોન એપ્લિકેશન્સનું નિર્માણ થાય છે તે નક્કર પાયો છે.