1:mod:`!contextvars` --- Context Variables 2========================================= 3 4.. module:: contextvars 5 :synopsis: Context Variables 6 7.. sectionauthor:: Yury Selivanov <yury@magic.io> 8 9-------------- 10 11This module provides APIs to manage, store, and access context-local 12state. The :class:`~contextvars.ContextVar` class is used to declare 13and work with *Context Variables*. The :func:`~contextvars.copy_context` 14function and the :class:`~contextvars.Context` class should be used to 15manage the current context in asynchronous frameworks. 16 17Context managers that have state should use Context Variables 18instead of :func:`threading.local` to prevent their state from 19bleeding to other code unexpectedly, when used in concurrent code. 20 21See also :pep:`567` for additional details. 22 23.. versionadded:: 3.7 24 25 26Context Variables 27----------------- 28 29.. class:: ContextVar(name, [*, default]) 30 31 This class is used to declare a new Context Variable, e.g.:: 32 33 var: ContextVar[int] = ContextVar('var', default=42) 34 35 The required *name* parameter is used for introspection and debug 36 purposes. 37 38 The optional keyword-only *default* parameter is returned by 39 :meth:`ContextVar.get` when no value for the variable is found 40 in the current context. 41 42 **Important:** Context Variables should be created at the top module 43 level and never in closures. :class:`Context` objects hold strong 44 references to context variables which prevents context variables 45 from being properly garbage collected. 46 47 .. attribute:: ContextVar.name 48 49 The name of the variable. This is a read-only property. 50 51 .. versionadded:: 3.7.1 52 53 .. method:: get([default]) 54 55 Return a value for the context variable for the current context. 56 57 If there is no value for the variable in the current context, 58 the method will: 59 60 * return the value of the *default* argument of the method, 61 if provided; or 62 63 * return the default value for the context variable, 64 if it was created with one; or 65 66 * raise a :exc:`LookupError`. 67 68 .. method:: set(value) 69 70 Call to set a new value for the context variable in the current 71 context. 72 73 The required *value* argument is the new value for the context 74 variable. 75 76 Returns a :class:`~contextvars.Token` object that can be used 77 to restore the variable to its previous value via the 78 :meth:`ContextVar.reset` method. 79 80 .. method:: reset(token) 81 82 Reset the context variable to the value it had before the 83 :meth:`ContextVar.set` that created the *token* was used. 84 85 For example:: 86 87 var = ContextVar('var') 88 89 token = var.set('new value') 90 # code that uses 'var'; var.get() returns 'new value'. 91 var.reset(token) 92 93 # After the reset call the var has no value again, so 94 # var.get() would raise a LookupError. 95 96 97.. class:: Token 98 99 *Token* objects are returned by the :meth:`ContextVar.set` method. 100 They can be passed to the :meth:`ContextVar.reset` method to revert 101 the value of the variable to what it was before the corresponding 102 *set*. 103 104 .. attribute:: Token.var 105 106 A read-only property. Points to the :class:`ContextVar` object 107 that created the token. 108 109 .. attribute:: Token.old_value 110 111 A read-only property. Set to the value the variable had before 112 the :meth:`ContextVar.set` method call that created the token. 113 It points to :attr:`Token.MISSING` if the variable was not set 114 before the call. 115 116 .. attribute:: Token.MISSING 117 118 A marker object used by :attr:`Token.old_value`. 119 120 121Manual Context Management 122------------------------- 123 124.. function:: copy_context() 125 126 Returns a copy of the current :class:`~contextvars.Context` object. 127 128 The following snippet gets a copy of the current context and prints 129 all variables and their values that are set in it:: 130 131 ctx: Context = copy_context() 132 print(list(ctx.items())) 133 134 The function has an *O*\ (1) complexity, i.e. works equally fast for 135 contexts with a few context variables and for contexts that have 136 a lot of them. 137 138 139.. class:: Context() 140 141 A mapping of :class:`ContextVars <ContextVar>` to their values. 142 143 ``Context()`` creates an empty context with no values in it. 144 To get a copy of the current context use the 145 :func:`~contextvars.copy_context` function. 146 147 Each thread has its own effective stack of :class:`!Context` objects. The 148 :term:`current context` is the :class:`!Context` object at the top of the 149 current thread's stack. All :class:`!Context` objects in the stacks are 150 considered to be *entered*. 151 152 *Entering* a context, which can be done by calling its :meth:`~Context.run` 153 method, makes the context the current context by pushing it onto the top of 154 the current thread's context stack. 155 156 *Exiting* from the current context, which can be done by returning from the 157 callback passed to the :meth:`~Context.run` method, restores the current 158 context to what it was before the context was entered by popping the context 159 off the top of the context stack. 160 161 Since each thread has its own context stack, :class:`ContextVar` objects 162 behave in a similar fashion to :func:`threading.local` when values are 163 assigned in different threads. 164 165 Attempting to enter an already entered context, including contexts entered in 166 other threads, raises a :exc:`RuntimeError`. 167 168 After exiting a context, it can later be re-entered (from any thread). 169 170 Any changes to :class:`ContextVar` values via the :meth:`ContextVar.set` 171 method are recorded in the current context. The :meth:`ContextVar.get` 172 method returns the value associated with the current context. Exiting a 173 context effectively reverts any changes made to context variables while the 174 context was entered (if needed, the values can be restored by re-entering the 175 context). 176 177 Context implements the :class:`collections.abc.Mapping` interface. 178 179 .. method:: run(callable, *args, **kwargs) 180 181 Enters the Context, executes ``callable(*args, **kwargs)``, then exits the 182 Context. Returns *callable*'s return value, or propagates an exception if 183 one occurred. 184 185 Example: 186 187 .. testcode:: 188 189 import contextvars 190 191 var = contextvars.ContextVar('var') 192 var.set('spam') 193 print(var.get()) # 'spam' 194 195 ctx = contextvars.copy_context() 196 197 def main(): 198 # 'var' was set to 'spam' before 199 # calling 'copy_context()' and 'ctx.run(main)', so: 200 print(var.get()) # 'spam' 201 print(ctx[var]) # 'spam' 202 203 var.set('ham') 204 205 # Now, after setting 'var' to 'ham': 206 print(var.get()) # 'ham' 207 print(ctx[var]) # 'ham' 208 209 # Any changes that the 'main' function makes to 'var' 210 # will be contained in 'ctx'. 211 ctx.run(main) 212 213 # The 'main()' function was run in the 'ctx' context, 214 # so changes to 'var' are contained in it: 215 print(ctx[var]) # 'ham' 216 217 # However, outside of 'ctx', 'var' is still set to 'spam': 218 print(var.get()) # 'spam' 219 220 .. testoutput:: 221 :hide: 222 223 spam 224 spam 225 spam 226 ham 227 ham 228 ham 229 spam 230 231 .. method:: copy() 232 233 Return a shallow copy of the context object. 234 235 .. describe:: var in context 236 237 Return ``True`` if the *context* has a value for *var* set; 238 return ``False`` otherwise. 239 240 .. describe:: context[var] 241 242 Return the value of the *var* :class:`ContextVar` variable. 243 If the variable is not set in the context object, a 244 :exc:`KeyError` is raised. 245 246 .. method:: get(var, [default]) 247 248 Return the value for *var* if *var* has the value in the context 249 object. Return *default* otherwise. If *default* is not given, 250 return ``None``. 251 252 .. describe:: iter(context) 253 254 Return an iterator over the variables stored in the context 255 object. 256 257 .. describe:: len(proxy) 258 259 Return the number of variables set in the context object. 260 261 .. method:: keys() 262 263 Return a list of all variables in the context object. 264 265 .. method:: values() 266 267 Return a list of all variables' values in the context object. 268 269 270 .. method:: items() 271 272 Return a list of 2-tuples containing all variables and their 273 values in the context object. 274 275 276asyncio support 277--------------- 278 279Context variables are natively supported in :mod:`asyncio` and are 280ready to be used without any extra configuration. For example, here 281is a simple echo server, that uses a context variable to make the 282address of a remote client available in the Task that handles that 283client:: 284 285 import asyncio 286 import contextvars 287 288 client_addr_var = contextvars.ContextVar('client_addr') 289 290 def render_goodbye(): 291 # The address of the currently handled client can be accessed 292 # without passing it explicitly to this function. 293 294 client_addr = client_addr_var.get() 295 return f'Good bye, client @ {client_addr}\r\n'.encode() 296 297 async def handle_request(reader, writer): 298 addr = writer.transport.get_extra_info('socket').getpeername() 299 client_addr_var.set(addr) 300 301 # In any code that we call is now possible to get 302 # client's address by calling 'client_addr_var.get()'. 303 304 while True: 305 line = await reader.readline() 306 print(line) 307 if not line.strip(): 308 break 309 310 writer.write(b'HTTP/1.1 200 OK\r\n') # status line 311 writer.write(b'\r\n') # headers 312 writer.write(render_goodbye()) # body 313 writer.close() 314 315 async def main(): 316 srv = await asyncio.start_server( 317 handle_request, '127.0.0.1', 8081) 318 319 async with srv: 320 await srv.serve_forever() 321 322 asyncio.run(main()) 323 324 # To test it you can use telnet or curl: 325 # telnet 127.0.0.1 8081 326 # curl 127.0.0.1:8081 327