サンプル
joblib 1.5.3: Handle closure serialization failures and backend fallback when switching joblib from loky to multiprocessing
検証済みサンプル — pypi joblib 1.5.3: Handle closure serialization failures and backend fallback when switching joblib from loky to multiprocessing. python 3.12 …
sha256:7786cfc40f400486765033eec7c04f3a21347d8f8513d308a4911a5ce6363569
このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。
合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。
MIT-0
実行証拠
宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。
- 証拠の基準
- 署名済みコントラクト合格
- 検証レシート
- 3
- ビルドした署名鍵
- 2
宣言された環境
python linux x64 python python pip
検証実行環境
| 環境 | コントラクト | ステージ | 実行日 |
|---|---|---|---|
| python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-15 |
| python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · python@1 |
2026-08-18 |
| python 3.12 · linux debian/x64 · docker ed25519:c1973797be207ac4 | FAIL | compile:SKIPPED · contract:FAIL · load:SKIPPED · resolve:PASS CONTAINER_RUN · python@1python:3.12-slim@sha256:09f7da3bc104… |
2026-09-07 |
ケース
HOW- ゴール
- Handle closure serialization failures and backend fallback when switching joblib from loky to multiprocessing
- パッケージ
- シンボル
-
- joblib.Parallel
- joblib.delayed
- joblib.wrap_non_picklable_objects
- joblib.parallel_backend
- joblib.parallel.DEFAULT_BACKEND
- joblib.parallel.get_active_backend
- joblib.externals.loky.backend.context.START_METHODS
- 環境
- python
- 作成日
- 2026-08-15T17:14:38Z
コントラクト
- assert jp.DEFAULT_BACKEND == 'loky' and isinstance(jp.get_active_backend()[0], jp.LokyBackend)
- assert 'loky' in loky_ctx.START_METHODS
- assert Parallel(n_jobs=2, backend='loky')(delayed(lambda x: x + 100)(i) for i in range(3)) == [100, 101, 102]
- assert Parallel(n_jobs=2, backend='multiprocessing')(delayed(lambda x: x + 100)(i)) raises (AttributeError, pickle.PicklingError)
- assert Parallel(n_jobs=2, backend='multiprocessing')(delayed(wrap_non_picklable_objects(lambda x: x + 100))(i) for i in range(3)) == [100, 101, 102]
- assert Parallel(n_jobs=2, backend='threading')(delayed(worker_with_lock)(lock, i) for i in range(3)) == [0, 2, 4]
- assert isinstance(Parallel(n_jobs=2, require='sharedmem')._backend, jp.ThreadingBackend)
- assert Parallel(backend='multiprocessing', require='sharedmem') raises ValueError
ファイル
- NOTES.md
- csx.json
- pyproject.toml
- requirements.lock
- requirements.txt
- test/contract.py
ソース
# Notes on joblib Multiprocessing and Serialization
## Prior Search Result
`search_known_solution` returned **MISS** (no relevant verified samples existed for `joblib` multiprocessing backend pickling and start methods; returned unrelated ecosystem samples).
## What a Naive Model Would Write
A naive model would write `Parallel(n_jobs=2, backend="multiprocessing")(delayed(lambda x: x * 2)(i) for i in range(10))` assuming `multiprocessing` behaves identically to the default `loky` backend.
## How the Wrong Version Fails
Loudly at runtime with `AttributeError: Can't pickle local object '<locals>.<lambda>'` or `pickle.PicklingError` because standard `multiprocessing` uses `pickle` rather than `cloudpickle` and cannot serialize dynamically defined closures without `@wrap_non_picklable_objects`.
{"case":{"caseId":"case:sha256:2eb36abd3109f462c3268b9f075a5a682959b51a5d44fcd3342fc0761e222107","constraints":{"runtime":"python"},"contract":["assert jp.DEFAULT_BACKEND == 'loky' and isinstance(jp.get_active_backend()[0], jp.LokyBackend)","assert 'loky' in loky_ctx.START_METHODS","assert Parallel(n_jobs=2, backend='loky')(delayed(lambda x: x + 100)(i) for i in range(3)) == [100, 101, 102]","assert Parallel(n_jobs=2, backend='multiprocessing')(delayed(lambda x: x + 100)(i)) raises (AttributeError, pickle.PicklingError)","assert Parallel(n_jobs=2, backend='multiprocessing')(delayed(wrap_non_picklable_objects(lambda x: x + 100))(i) for i in range(3)) == [100, 101, 102]","assert Parallel(n_jobs=2, backend='threading')(delayed(worker_with_lock)(lock, i) for i in range(3)) == [0, 2, 4]","assert isinstance(Parallel(n_jobs=2, require='sharedmem')._backend, jp.ThreadingBackend)","assert Parallel(backend='multiprocessing', require='sharedmem') raises ValueError"],"goal":"Handle closure serialization failures and backend fallback when switching joblib from loky to multiprocessing","kind":"HOW","packages":["pkg:pypi/joblib@1.5.3"],"schemaVersion":1,"symbols":["joblib.Parallel","joblib.delayed","joblib.wrap_non_picklable_objects","joblib.parallel_backend","joblib.parallel.DEFAULT_BACKEND","joblib.parallel.get_active_backend","joblib.externals.loky.backend.context.START_METHODS"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/joblib@1.5.3"],"schemaVersion":1,"symbols":["joblib.Parallel","joblib.delayed","joblib.wrap_non_picklable_objects","joblib.parallel_backend","joblib.parallel.DEFAULT_BACKEND","joblib.parallel.get_active_backend","joblib.externals.loky.backend.context.START_METHODS"],"verifierAdapter":"python@1"}
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "sample-joblib-start-method"
version = "0.1.0"
dependencies = [
"joblib==1.5.3",
]
joblib==1.5.3
joblib==1.5.3
import pickle
import threading
from joblib import Parallel, delayed, parallel_backend, wrap_non_picklable_objects
import joblib.parallel as jp
import joblib.externals.loky.backend.context as loky_ctx
def _thread_worker(lock, item):
with lock:
return item * 2
def main():
# 1. Joblib defaults to 'loky' backend, NOT 'multiprocessing'
active_backend, _ = jp.get_active_backend()
assert jp.DEFAULT_BACKEND == "loky"
assert isinstance(active_backend, jp.LokyBackend)
# 2. Loky backend uses dedicated process context and cloudpickle serialization for closures
assert "loky" in loky_ctx.START_METHODS
base = 100
local_closure = lambda x: x + base
res_loky = Parallel(n_jobs=2, backend="loky")(
delayed(local_closure)(i) for i in range(3)
)
assert res_loky == [100, 101, 102]
# 3. Switching to 'multiprocessing' uses standard pickle which fails on raw local closures
mp_failed = False
try:
Parallel(n_jobs=2, backend="multiprocessing")(
delayed(local_closure)(i) for i in range(3)
)
except (AttributeError, pickle.PicklingError):
mp_failed = True
assert mp_failed, "backend='multiprocessing' must fail on un-picklable local closure"
# 4. wrap_non_picklable_objects enables raw closures to work with backend='multiprocessing'
wrapped = wrap_non_picklable_objects(local_closure)
res_mp_wrapped = Parallel(n_jobs=2, backend="multiprocessing")(
delayed(wrapped)(i) for i in range(3)
)
assert res_mp_wrapped == [100, 101, 102]
# 5. Non-serializable state (like threading.Lock) fails in process backends but works in threading
lock = threading.Lock()
loky_lock_failed = False
try:
Parallel(n_jobs=2, backend="loky")(
delayed(_thread_worker)(lock, i) for i in range(3)
)
except Exception:
loky_lock_failed = True
assert loky_lock_failed, "loky process pool cannot serialize threading.Lock"
res_threads = Parallel(n_jobs=2, backend="threading")(
delayed(_thread_worker)(lock, i) for i in range(3)
)
assert res_threads == [0, 2, 4]
# 6. require='sharedmem' automatically switches backend context to ThreadingBackend
with parallel_backend("multiprocessing"):
p_shared = Parallel(n_jobs=2, require="sharedmem")
assert isinstance(p_shared._backend, jp.ThreadingBackend)
res_shared = p_shared(delayed(_thread_worker)(lock, i) for i in range(3))
assert res_shared == [0, 2, 4]
# 7. Explicit contradictory arguments raise ValueError
contradiction_caught = False
try:
Parallel(backend="multiprocessing", require="sharedmem")
except ValueError:
contradiction_caught = True
assert contradiction_caught, "Contradictory backend and require='sharedmem' must raise ValueError"
if __name__ == "__main__":
main()