I am completely newb on asyncio and ContextVars
, I just read up what's new in 3.7 and discovered ContextVars
, I struggle to understand it's usage, all I know it's helpful in coroutines, instead of using thread.local
should use ContextVars
. But none of the official doc and top google search result could help me truely understand its purpose.
So is convextvars shared across modules? I tried:
example.py
from contextvars import ContextVar
number = ContextVar('number', default=100)
number.set(1)
then I try to import number.py
(playground) Jamess-MacBook-Pro-2:playground jlin$ python3.7
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> from contextvars import ContextVar
>>> number = ContextVar('number', default=200)
>>> number.get()
200
I was expecting number.get()
would return 1, but obviously I have understood its purpose wrong.
Could someone please help me understand this?
Assume your use case is to use python thread.local
to store your thread global variable inside multi thread application.
For example you store django request
globally in thread.local
request
instanceNo imagine you handle HTTP requests in asyncio as non blocking code executed in the same python thread.
thread.local
isn't going to work, because multiple concurrent requests get processed in the same python threadthread.local
variable and all your code has access to latest (incorrect) request
instanceIn this case you use ContextVars
designed to be used for this use case inside non blocking concurrent jobs running in same python thread.
You are reassigning the value of number
. Directly call the variable from the module, e.g. example.number.get()
.
A simple application is substituting a global variable.
Given
import random
import contextvars as cv
Code
Here we'll imitate a random walk. Like a global variable, we are able to share state between functions:
move = cv.ContextVar("move", default="")
def go_left():
value = move.get()
move.set(value + "L")
def go_right():
value = move.get()
move.set(value + "R")
def random_walk(steps):
directions = [go_left, go_right]
while steps:
random.choice(directions)()
steps -= 1
return move.get()
Demo
The ContextVar
acts as a global variable that is updated by random events:
random_walk(1)
# 'R'
random_walk(2)
# 'RLL'
random_walk(3)
# 'RLLLRL'
Beyond a regular global variable, ContextVar
:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With