This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: loop.run_in_executor should propagate current contextvars
Type: enhancement Stage: resolved
Components: asyncio Versions: Python 3.9
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: asvetlov, hellysmile, yselivanov
Priority: normal Keywords: patch

Created on 2018-06-30 23:26 by hellysmile, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 8035 closed hellysmile, 2018-06-30 23:33
PR 9688 closed hellysmile, 2018-10-03 14:06
Messages (14)
msg320814 - (view) Author: Viktor Kovtun (hellysmile) * Date: 2018-06-30 23:26
PEP 567 supports copying context into another threads, but for asyncio users each call `run_in_executor` requires explicit context propagation

For end users expected behavior that context is copied automatically
msg320817 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-06-30 23:56
I considered enabling that, but in the end decided not to. The reason is that it's possible to use a ProcessPoolExecutor with run_in_execuror(), and context cars currently don't support pickling (and probably never will). We can't have a single api that sometimes works with contextvars and sometimes doesn't.

So this is a "won't fix".
msg320818 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-06-30 23:59
As a workaround you can subclass the ThreadPoolExecutor and set it as a default executor.
msg320819 - (view) Author: Viktor Kovtun (hellysmile) * Date: 2018-07-01 00:10
What about to check instance of executor and depending on that propagate contextvars or not?

As well to raise RuntimeError for ProcessPoolExecutor with provided context?

I assume, that ProcessPoolExecutor as executor is not so popular in real world, but I can not provide any stats.

Different behavior is defiantly at least weird, but do not support natively what is technically expected also strange.

https://docs.python.org/3.7/library/contextvars.html#asyncio-support `Context variables are natively supported in asyncio` is hard for end users.

Each use case of contextvars + run_in_executor will produce copy-paste boilerplate

As for me it is very similar to the `asyncio.get_event_loop()` history
msg320820 - (view) Author: Viktor Kovtun (hellysmile) * Date: 2018-07-01 00:13
`ProcessPoolExecutor as executor is not so popular in real world` - as executor for asyncio
msg326812 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-10-01 16:14
So we're deprecating passing non-ThreadPoolExecutor instances to loop.set_default_executor.  In 3.9 that will trigger an error.

For this issue we have basically the next few options:

(1) Do nothing;

(2) Fix "run_in_executor" to start copying and running in correct context automatically

(3) Add a new keyword-only parameter to "run_in_executor": "retain_context=False"

(4) Design a new async/await friendly API for using thread- and process-pools.

Now, (4) will happen.  The "run_in_executor" method is low-level and requires accessing the event loop to use it.  We probably have enough time to design this new API before 3.8.

As for implementing (3) in 3.8 -- I'd be OK with that too.  Andrew, your thoughts?
msg326813 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-10-01 16:20
One problem with (3) is what will happen if someone uses "retain_context=True" and a ProcessPoolExecutor.  It has to fail in a graceful and obvious way.
msg326950 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2018-10-03 09:06
I vote on not changing `run_in_executor` behavior if we cannot make it work with `ProcessPoolExecutor`.

If a new API will solve the problem -- that's fine.
Until it landed the explicit context propagation is the satisfactory solution.
msg326972 - (view) Author: Viktor Kovtun (hellysmile) * Date: 2018-10-03 14:09
I've created new pull request https://github.com/python/cpython/pull/9688 with the implementation of proposed changes
msg326975 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-10-03 14:32
[Andrew]
> I vote on not changing `run_in_executor` behavior if we cannot make it work with `ProcessPoolExecutor`.

> If a new API will solve the problem -- that's fine.
Until it landed the explicit context propagation is the satisfactory solution.


I'm not sure I understand.  Should we close this issue or you're OK with (3)?
msg326978 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2018-10-03 14:50
I prefer (4) but can live with (3)

It is a new feature for Python 3.8 anyway, no need to rush
msg326981 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2018-10-03 15:05
> It is a new feature for Python 3.8 anyway, no need to rush

Yep, I agree. Let's see if we end up having a new nice high-level API in 3.8; if not we go for (3).
msg350467 - (view) Author: Viktor Kovtun (hellysmile) * Date: 2019-08-25 17:35
Hey, as I see there is no new API yet.

Can we take a look again on 3) ?

I'll be happy to update PR 9688
msg415908 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2022-03-23 20:57
contextvars and run_in_executor() cannot be used together with process executor.

asyncio.to_thread() runs with a copy of the current context.
Available since Python 3.9

https://docs.python.org/3/library/asyncio-task.html?highlight=to_thread#asyncio.to_thread
History
Date User Action Args
2022-04-11 14:59:02adminsetgithub: 78195
2022-03-23 20:57:22asvetlovsetstatus: open -> closed
resolution: postponed -> out of date
messages: + msg415908

stage: patch review -> resolved
2019-10-20 20:20:18cheryl.sabellasetversions: + Python 3.9, - Python 3.8
2019-08-25 17:35:11hellysmilesetmessages: + msg350467
2018-10-03 15:05:19yselivanovsetstatus: pending -> open
versions: - Python 3.7
2018-10-03 15:05:09yselivanovsetstatus: open -> pending
type: enhancement
resolution: postponed
messages: + msg326981
2018-10-03 14:50:43asvetlovsetmessages: + msg326978
2018-10-03 14:32:47yselivanovsetmessages: + msg326975
2018-10-03 14:09:06hellysmilesetmessages: + msg326972
2018-10-03 14:06:42hellysmilesetpull_requests: + pull_request9074
2018-10-03 09:06:21asvetlovsetmessages: + msg326950
2018-10-01 16:20:08yselivanovsetmessages: + msg326813
2018-10-01 16:14:38yselivanovsetmessages: + msg326812
2018-07-01 00:13:53hellysmilesetmessages: + msg320820
2018-07-01 00:10:13hellysmilesetmessages: + msg320819
2018-06-30 23:59:12yselivanovsetmessages: + msg320818
2018-06-30 23:56:26yselivanovsetmessages: + msg320817
2018-06-30 23:33:17hellysmilesetkeywords: + patch
stage: patch review
pull_requests: + pull_request7645
2018-06-30 23:26:24hellysmilecreate