Azure / Azure/azure-functions-python-worker
[Python 3.14 proxy worker] Missing sys.modules["__main__"] breaks multiprocessing spawn
- 主要语言
- Python
- 星标
- 357
- 派生
- 116
- 平均合并
- 32 分钟
- 30 天内合并 PR
- 1
描述
### Description
The Azure Functions Python 3.14 proxy worker removes `__main__` from
`sys.modules` before invoking application code.
As a result, Python's standard `multiprocessing` spawn context fails during
`Process.start()`, before the child process or its target function begins
executing.
This is not specific to any third-party package. The minimal reproduction uses
only `azure-functions` and the Python standard library.
### Environment
- Azure Functions Python runtime: 3.14
- Python: 3.14.6
- Azure Functions Core Tools: 4.12.0
- Functions runtime: 4.1048.200.26180
- Programming model: Python v2
- `azure-functions` application package: 2.2.0
- Reproduced locally inside the Functions worker
- The same failure was observed after deploying the application to Azure Functions on Python 3.14
The same application code worked on the Python 3.12 Functions runtime.
### Minimal reproduction
```python
import multiprocessing
import sys
import azure.functions as func
app = func.FunctionApp()
def child_process() -> None:
return None
@app.route(route="multiprocessing-repro")
def multiprocessing_repro(req: func.HttpRequest) -> func.HttpResponse:
main_present = "__main__" in sys.modules
context = multiprocessing.get_context("spawn")
process = context.Process(target=child_process)
process.start()
process.join()
return func.HttpResponse(
f"__main__ present: {main_present}; exit code: {process.exitcode}"
)
```
Start the application using Core Tools with Python 3.14 and invoke
`/api/multiprocessing-repro`.
### Actual behavior
`"__main__" in sys.modules` is false during the function invocation, and
`Process.start()` raises:
```text
Traceback (most recent call last):
File ".../multiprocessing/process.py", line 121, in start
self._popen = self._Popen(self)
File ".../multiprocessing/context.py", line 289, in _Popen
return Popen(process_obj)
File ".../multiprocessing/popen_spawn_posix.py", line 32, in __init__
super().__init__(process_obj)
File ".../multiprocessing/popen_fork.py", line 19, in __init__
self._launch(process_obj)
File ".../multiprocessing/popen_spawn_posix.py", line 42, in _launch
prep_data = spawn.get_preparation_data(process_obj._name)
File ".../multiprocessing/spawn.py", line 164, in get_preparation_data
main_module = sys.modules["__main__"]
KeyError: "__main__"
```
The failure occurs before the child process starts.
### Expected behavior
The Functions worker should retain a valid `__main__` module, or otherwise
initialize the application environment so that standard-library
`multiprocessing` spawn works inside a function invocation.
### Investigation
The Python 3.14 worker uses `proxy_worker`. Its dependency cleanup appears to
remove modules from `sys.modules` based on their file location. It excludes
modules whose names begin with `proxy_worker`, but does not appear to exclude
`__main__`.
That appears to leave the invocation environment without the module required
by `multiprocessing.spawn.get_preparation_data()`.
Launching an explicit Python subprocess with an importable module works in the
same Functions-host process, confirming that the failure is specifically in
the `multiprocessing` spawn preparation path.
### Impact
Any application or dependency that uses the standard-library spawn context can
fail under the Python 3.14 Functions worker. In our application this prevented
all isolated document conversions from starting, regardless of document type.
### Related issue
Related historical issue: #1094 reported the same missing-`__main__` worker
condition on Python 3.9 through a different caller.
This report concerns the Python 3.14 proxy worker and reproduces through:
```python
multiprocessing.get_context("spawn").Process(...).start()
```
It is therefore related behavior, but not the same caller or worker
implementation.
贡献指南
调研方向
首先定位调查中描述的 Python 3.14 proxy_worker 依赖清理路径,并使用最小的 multiprocessing spawn 示例复现该故障。追踪 __main__ 被移除的原因,然后验证复现代码能够成功启动并 join 子进程,同时不会破坏 worker 的清理行为。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- azure, python
- 领域
- backend, cloud
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 55/100