3

How can I pass context from on asynchronous method call to another one - without using method parameters?

I need the feature to enrich log messages with a kind of flow ID so that I can easily trace all log messages of a specific call method flow.

I use Python's async and await keywords (Python 3.5.x).

4 Answers 4

2

You should use Context Variables introduced in Python 3.7, and I have a polyfill for Python < 3.7 as aiocontextvars.

Previous answer:

You may want to take a look at tasklocals and aiolocals.

Sign up to request clarification or add additional context in comments.

2 Comments

The documentation of both projects looks promising.
I found it tricky to do it right especially when using third-party loops offering more efficient Task implementation - here's what I did recently: github.com/fantix/gino/blob/master/gino/local.py
1

I solved the problem by setting a custom task factory. It turned out that having a context per task (in comparison to a context per async call) was sufficient for me.

1 Comment

Interesting, didn't know about that one :)
0

I'm working on aiotask-context package. It's a really simple way of passing context between tasks (called with await or yield from). If you don't wan't to use the package you can still use the idea :).

I'm working on how to propagate it for the ensure_future calls too.

Comments

0
import contextvars
c_id = contextvars.ContextVar("context_id", default=None)

def get_context_id():
    return c_id.get()

def set_context_id(value):
    c_id.set(value)

I struggled a lot for getting this right. If anyone is still searching for the answer then they can refer here. This works with Python3.7 onwards.

  • Create an instance of contextvars.ContextVar.
  • Here you can give the context variable name and a default value for that variable, the default value will be used in case the variable is not found in the current context.
  • Set the value using the setter and you can get the same value using the getter inside same context.
  • Define ContextVar at the top level once, and not inside closures(i.e. functions or class etc.) as garbage collection for context is not proper.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.