2

In Python async function I'am creating ContextVar, task and attaching callback to it:

bbb = contextvars.ContextVar('aaa')
bbb.set(3)
task = self.loop.create_task(self.someFunc())
task.add_done_callback(self.commonCallback)
bbb.set(4)

In callback I first start debugger:

def commonCallback(self, result):
 pdb.set_trace()
 try:
  r = result.result()
  print(r)
 except:
  self.log.exception('commonCallback')

And in debugger:

-> try:
(Pdb) bbb.get()
*** NameError: name 'bbb' is not defined
(Pdb) ctx = contextvars.copy_context()
(Pdb) print(list(ctx.items()))
[(<ContextVar name='aaa' at 0xa8245df0>, 3)]
(Pdb) 

ContextVar is there, but I can't access it. So, I am missing something, but can't find what?

ljweko
  • 35
  • 5
  • Why do you expect the `bbb` local variable defined in one function to be accessible in the `commonCallback` function defined elsewhere in the code? The [documentation](https://docs.python.org/3/library/contextvars.html) states that "Context Variables should be created at the top module level". – user4815162342 Apr 11 '21 at 07:24
  • @user4815162342 Thanks, that was it. I knew it was trivial, and it was, as usual. I just couldn't see it. Sadly, I do not have enough reputation to upvote comment. – ljweko Apr 11 '21 at 18:50
  • No problem, I've now posted a similar suggestion as an answer which you can accept. – user4815162342 Apr 11 '21 at 20:36

2 Answers2

2

The bbb local variable is defined in one place, so it won't be automatically accessible in another, such as the commonCallback function defined elsewhere in the code. The documentation states that "Context Variables should be created at the top module level", so you should try that first.

user4815162342
  • 141,790
  • 18
  • 296
  • 355
0

You can get a value from context without importing top level module. contextvars.Context has __iter__ method. And you can use a for loop to get the value:

def get_ctx_var_value(ctx, var_name, default_value=None):
    for var in ctx:
        if var.name == var_name:
            return ctx[var]
    return default_value

ctx = contextvars.copy_context()
var_value = get_ctx_var_value(ctx, 'aaa')