contextvars上下文变量


此模块提供API来管理,存储和访问context-localstate。ContextVar类用于声明和使用Context Variablescopy_context()功能和Contextclass应该用于管理异步框架中的当前上下文.

有状态的文本管理器应该使用Context Variables而不是threading.local()在并发代码中使用时,防止他们的状态意外地从其他代码中出来.

也可以看看 PEP 567 了解更多详情.

版本3.7.

上下文变量

class contextvars.ContextVarname [, *, default]

这个类用于声明一个新的Context变量,例如:

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

所需的name参数用于内省和调试目的.

可选关键字default当在当前上下文中找不到变量的值时,ContextVar.get()返回参数.

重要的上下文变量应该在顶层模块级别创建,永远不会在闭包中创建。Context对象保存对上下文变量的强引用,这可以防止上下文变量被正确地垃圾收集.

name

变量的名称。这是一个只读属性.

新版本3.7.1.

get ( [default])

返回当前上下文的上下文变量的值.

如果当前上下文中的变量没有值,则方法将:

  • 返回值default方法的参数,如果提供的话;或
  • 返回上下文变量的默认值,如果它是用一个创建的;或
  • 举起LookupError.
setvalue

调用在currentcontext中为上下文变量设置一个新值

required value参数是contextvariable的新值

返回Token对象,可用于通过ContextVar.reset()将变量恢复为之前的值method

reset// (token)

将上下文变量重置为ContextVar.set()创建token之前的值。

例如:

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

Token对象由ContextVar.set()方法。他们可以传到ContextVar.reset()变量的值恢复到相应的set.

Token.var

只读属性。指向ContextVar创建令牌的对象.

Token.old_value

只读属性。设置为ContextVar.set()创建令牌的方法调用。它指向Token.MISSING在调用之前没有设置变量

Token.MISSING

使用的标记对象Token.old_value.

手动上下文管理

contextvars.copy_context

返回当前Context宾语。

以下代码段获取当前上下文的副本并打印所有变量及其中设置的值:

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

该函数具有O(1)复杂度,即对于具有少量上下文变量上下文以及具有大量上下文变量的上下文同样快速地工作.

class contextvars.Context

的映射ContextVars他们的价值观

Context()创建一个没有值的空上下文。要获取当前上下文的副本,请使用copy_context() function.

Context实现collections.abc.Mappinginterface

run// (callable, *args, **kwargs)

执行callable(*args, **kwargs)在上下文对象中的代码调用run方法。如果发生了一个异常,则返回执行程序的结果传播异常.

任何更改callable使上下文对象中包含的任何上下文变量

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"

该方法引发一个RuntimeError从多个OS线程调用samecontext对象时,或者在调用时被调用

copy// ()

返回上下文的浅层副本对象

var in context

返回True如果contextvar设置值;返回False否则

context[var]

//返回var ContextVar变量的值。如果在上下文对象中没有设置变量,则KeyError被引发

get// (var [, default]

如果var具有contextobject中的值,则返回var的值。否则返回default。如果没有给出default,则返回None.

iter(context)

将一个迭代器返回到存储在contextobject中的变量.

len(proxy)

返回上下文对象中设置的变量数.

keys

返回上下文对象中所有变量的列表.

values ()

返回上下文对象中所有变量值的列表.

items

返回包含上下文对象中所有变量及其值的2元组列表.

asynciosupport

本机支持上下文变量在asyncio并且无需任何额外配置即可使用。例如,这里是一个简单的echo服务器,它使用一个上下文变量来使一个远程客户端的地址在Task中处理该客户端:

import asyncioimport contextvarsclient_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

评论被关闭。