-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
Description
Bug report
Bug description:
Bug report
Python version
3.14.0a5+ (also reproducible on 3.14.0b1+)
Works fine on 3.10–3.13.
OS
Linux (where forkserver is the new default start method)
What happened
Python 3.14 changed the default multiprocessing start method on Linux from fork to
forkserver (per #84559). The forkserver implementation in Lib/multiprocessing/forkserver.py
serializes sys.path using %r formatting into a command string that is later exec()'d
in child processes.
If sys.path contains non-string objects (e.g. pathlib.PosixPath), repr() produces
PosixPath('/some/path') which fails with NameError in the child process because
pathlib is not imported in the exec() context.
While sys.path is documented to contain strings, Python has never enforced this, and
pathlib.Path objects work fine in sys.path for import resolution. Many codebases
(including via sys.path.append(Path(...))) have relied on this for years without issues
because fork copied memory directly without serialization.
Minimal reproduction
import sys
from pathlib import Path
from concurrent.futures import ProcessPoolExecutor
sys.path.append(Path("/opt/some-package"))
def worker(x):
return x * 2
if __name__ == "__main__":
with ProcessPoolExecutor(max_workers=2) as executor:
results = list(executor.map(worker, range(5)))
print(f"Results: {results}")Expected
Program completes successfully (as it does on Python 3.10–3.13).
Actual
NameError: name 'PosixPath' is not defined
Root Cause
Lib/multiprocessing/forkserver.py line ~80:
cmd = ('from multiprocessing.forkserver import main; ' +
'main(%d, %d, %r, **%r)')
The %r on sys.path (passed via spawn.get_preparation_data()) doesn't convert Path objects to strings. A simple fix would be to normalize sys.path entries to str() in get_preparation_data(), or use os.fspath() on each entry.
Break is from #84559 (changing default to forkserver)
CPython versions tested on:
3.14
Operating systems tested on:
Linux