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