Python 3.7 - contextvars

संदर्भ - प्रसंग चर




python

संदर्भ - प्रसंग चर

यह मॉड्यूल संदर्भ-स्थानीय स्थिति को प्रबंधित करने, संग्रहीत करने और एक्सेस करने के लिए एपीआई प्रदान करता है। ContextVar क्लास का उपयोग Context Variables को घोषित करने और काम करने के लिए किया जाता है। copy_context() फ़ंक्शन और Context वर्ग का उपयोग अतुल्यकालिक फ्रेमवर्क में वर्तमान संदर्भ को प्रबंधित करने के लिए किया जाना चाहिए।

जिन कॉन्टेक्स्ट मैनेजरों के पास स्टेट है, उन्हें threading.local() बजाय कॉन्टेक्ट वेरिएबल्स का उपयोग करना चाहिए ताकि उनके राज्य को अनियंत्रित रूप से दूसरे कोड में रक्तस्राव से रोका जा सके, जब समवर्ती कोड का उपयोग किया जाता है।

अतिरिक्त विवरण के लिए PEP 567 भी देखें।

संस्करण 3.7 में नया।

प्रसंग चर

class contextvars.ContextVar(name[, *, default])

इस वर्ग का उपयोग एक नया प्रसंग चर घोषित करने के लिए किया जाता है, जैसे:

var: ContextVar[int] = ContextVar('var', default=42)

आवश्यक नाम पैरामीटर का उपयोग आत्मनिरीक्षण और डिबग उद्देश्यों के लिए किया जाता है।

वैकल्पिक कीवर्ड-केवल डिफ़ॉल्ट पैरामीटर ContextVar.get() द्वारा लौटाया जाता है जब चर का कोई मान वर्तमान संदर्भ में नहीं मिलता है।

महत्वपूर्ण: संदर्भ चर को शीर्ष मॉड्यूल स्तर पर बनाया जाना चाहिए और कभी भी बंद नहीं होना चाहिए। Context ऑब्जेक्ट संदर्भ चर के लिए मजबूत संदर्भ रखते हैं जो संदर्भ चर को ठीक से एकत्र किए जाने से रोकता है।

name

चर का नाम। यह केवल पढ़ने के लिए संपत्ति है।

संस्करण 3.7.1 में नया।

get([default])

वर्तमान संदर्भ के लिए संदर्भ चर के लिए एक मान लौटाएं।

यदि वर्तमान संदर्भ में चर का कोई मूल्य नहीं है, तो विधि होगी:

  • यदि प्रदान की गई विधि के डिफ़ॉल्ट तर्क का मान लौटाएं; या
  • संदर्भ चर के लिए डिफ़ॉल्ट मान लौटाएं, अगर यह एक के साथ बनाया गया था; या
  • एक LookupError
set(value)

वर्तमान संदर्भ में संदर्भ चर के लिए एक नया मान सेट करने के लिए कॉल करें।

संदर्भ चर के लिए आवश्यक मान तर्क नया मान है।

एक Token ऑब्जेक्ट लौटाता है जिसका उपयोग ContextVar.reset() विधि के माध्यम से चर को उसके पिछले मान को पुनर्स्थापित करने के लिए किया जा सकता है।

reset(token)

संदर्भ मान को उस संदर्भ में रीसेट करें, जो ContextVar.set() से पहले था जो टोकन बनाया गया था।

उदाहरण के लिए:

var = ContextVar('var')

token = var.set('new value')
# code that uses 'var'; var.get() returns 'new value'.
var.reset(token)

# After the reset call the var has no value again, so
# var.get() would raise a LookupError.
class contextvars.Token

टोकन ऑब्जेक्ट्स को ContextVar.set() विधि द्वारा लौटाया जाता है। वे संबंधित सेट के पहले चर के मान को वापस करने के लिए ContextVar.reset() विधि से पारित किए जा सकते हैं।

Token.var

केवल पढ़ने के लिए संपत्ति। टोकन बनाने वाले ContextVar ऑब्जेक्ट को ContextVar करता है।

Token.old_value

केवल पढ़ने के लिए संपत्ति। ContextVar.set() विधि कॉल से पहले वैरिएबल के मान पर सेट करें जिसने टोकन बनाया है। यह Token.MISSING को Token.MISSING है। Token.MISSING वह चर है जिसे कॉल से पहले सेट नहीं किया गया था।

Token.MISSING

Token.old_value द्वारा उपयोग की जाने Token.old_value मार्कर वस्तु।

मैनुअल संदर्भ प्रबंधन

contextvars.copy_context()

वर्तमान Context वस्तु की एक प्रति लौटाता है।

निम्नलिखित स्निपेट को वर्तमान संदर्भ की एक प्रति मिलती है और इसमें सभी चर और उनके मूल्य अंकित होते हैं:

ctx: Context = copy_context()
print(list(ctx.items()))

फ़ंक्शन में एक O (1) जटिलता है, यानी कुछ संदर्भ चर वाले संदर्भों के लिए समान रूप से तेजी से काम करता है और उन संदर्भों के लिए जो उनमें से बहुत से हैं।

class contextvars.Context

उनके मूल्यों के ContextVar का मानचित्रण।

Context() एक खाली संदर्भ बनाता है जिसमें कोई मूल्य नहीं है। वर्तमान संदर्भ की एक प्रति प्राप्त करने के लिए copy_context() फ़ंक्शन का उपयोग करें।

संदर्भ collections.abc.Mapping .abc.Mapping इंटरफ़ेस को लागू करता है।

run(callable, *args, **kwargs)

निष्पादन callable(*args, **kwargs) कॉल करने callable(*args, **kwargs) कोड को संदर्भ ऑब्जेक्ट में रन विधि कहा जाता है। निष्पादन का परिणाम लौटाएं या यदि कोई हुआ तो एक अपवाद का प्रचार करें।

कॉल करने योग्य किसी भी संदर्भ चर में कोई भी परिवर्तन संदर्भ ऑब्जेक्ट में शामिल किया जाएगा:

var = ContextVar('var')
var.set('spam')

def main():
    # 'var' was set to 'spam' before
    # calling 'copy_context()' and 'ctx.run(main)', so:
    # var.get() == ctx[var] == 'spam'

    var.set('ham')

    # Now, after setting 'var' to 'ham':
    # var.get() == ctx[var] == 'ham'

ctx = copy_context()

# Any changes that the 'main' function makes to 'var'
# will be contained in 'ctx'.
ctx.run(main)

# The 'main()' function was run in the 'ctx' context,
# so changes to 'var' are contained in it:
# ctx[var] == 'ham'

# However, outside of 'ctx', 'var' is still set to 'spam':
# var.get() == 'spam'

जब एक से अधिक OS थ्रेड से एक ही संदर्भ ऑब्जेक्ट पर कॉल किया जाता है, या जब पुनरावर्ती कहा जाता है, तो यह विधि एक RuntimeError उठाती है।

copy()

संदर्भ वस्तु की उथली प्रति लौटाएं।

var in context

यदि संदर्भ में var सेट का मान है तो True लौटें; अन्यथा False

context[var]

Var ContextVar वैरिएबल का मान ContextVar । यदि चर संदर्भ ऑब्जेक्ट में सेट नहीं किया गया है, तो एक KeyError उठाया जाता है।

get(var[, default])

यदि var का संदर्भ ऑब्जेक्ट में मान है, तो var के लिए मान लौटाएँ। अन्यथा डिफ़ॉल्ट लौटें। यदि डिफ़ॉल्ट नहीं दिया गया है, तो None लौटाएं।

iter(context)

संदर्भ ऑब्जेक्ट में संग्रहीत चर पर एक पुनरावृत्त लौटें।

len(proxy)

संदर्भ ऑब्जेक्ट में सेट किए गए चर की संख्या लौटाएं।

keys()

संदर्भ ऑब्जेक्ट में सभी चर की सूची लौटाएं।

values()

संदर्भ ऑब्जेक्ट में सभी चर के मानों की सूची लौटाएं।

items()

संदर्भ ऑब्जेक्ट में सभी चर और उनके मूल्यों वाले 2-टुपल्स की सूची लौटाएं।

asyncio समर्थन करते हैं

प्रसंग चर मूल रूप से asyncio में समर्थित हैं और बिना किसी अतिरिक्त कॉन्फ़िगरेशन के उपयोग के लिए तैयार हैं। उदाहरण के लिए, यहां एक सरल इको सर्वर है, जो उस कार्य के बारे में एक दूरस्थ क्लाइंट के पते को बनाने के लिए एक संदर्भ चर का उपयोग करता है जो उस वेबसाइट को उपलब्ध कराता है:

import asyncio
import contextvars

client_addr_var = contextvars.ContextVar('client_addr')

def render_goodbye():
    # The address of the currently handled client can be accessed
    # without passing it explicitly to this function.

    client_addr = client_addr_var.get()
    return f'Good bye, client @ {client_addr}\n'.encode()

async def handle_request(reader, writer):
    addr = writer.transport.get_extra_info('socket').getpeername()
    client_addr_var.set(addr)

    # In any code that we call is now possible to get
    # client's address by calling 'client_addr_var.get()'.

    while True:
        line = await reader.readline()
        print(line)
        if not line.strip():
            break
        writer.write(line)

    writer.write(render_goodbye())
    writer.close()

async def main():
    srv = await asyncio.start_server(
        handle_request, '127.0.0.1', 8081)

    async with srv:
        await srv.serve_forever()

asyncio.run(main())

# To test it you can use telnet:
#     telnet 127.0.0.1 8081