{"id":8492,"library":"pyleak","title":"Pyleak","description":"Pyleak is a Python library inspired by Go's goleak, designed to detect leaked asyncio tasks, threads, and event loop blocking in asynchronous Python applications. The current version is 0.2.0, with frequent minor and patch releases, indicating active development.","status":"active","version":"0.2.0","language":"en","source_language":"en","source_url":"https://github.com/deepankarm/pyleak","tags":["asyncio","testing","debugging","leak detection","concurrency","performance"],"install":[{"cmd":"pip install pyleak","lang":"bash","label":"Install pyleak"}],"dependencies":[],"imports":[{"symbol":"LeakDetector","correct":"from pyleak import LeakDetector"},{"note":"As of v0.2.0, no_event_loop_blocking must be used as an async context manager, not a decorator.","wrong":"@no_event_loop_blocking\nasync def func(): ...","symbol":"no_event_loop_blocking","correct":"from pyleak import no_event_loop_blocking"},{"symbol":"CombinedLeakDetector","correct":"from pyleak import CombinedLeakDetector"}],"quickstart":{"code":"import asyncio\nfrom pyleak import LeakDetector\n\nasync def create_leak():\n    # A task that runs forever, simulating a leak\n    async def forever_task():\n        while True:\n            await asyncio.sleep(100)\n    asyncio.create_task(forever_task())\n\nasync def main():\n    async with LeakDetector():\n        await create_leak()\n        print(\"This will run, but a leak was created.\")\n    # LeakDetector exits, will raise AssertionError if leaks are found\n    print(\"LeakDetector exited, no assertion was raised (this line won't be reached if a leak is present).\")\n\nif __name__ == \"__main__\":\n    # To see the AssertionError from the leak:\n    # asyncio.run(main())\n    \n    # To avoid the assertion for demonstration:\n    try:\n        asyncio.run(main())\n    except AssertionError as e:\n        print(f\"Caught expected leak: {e}\")","lang":"python","description":"This example demonstrates how to use `LeakDetector` to identify unawaited or long-running asyncio tasks that are not properly shut down, which pyleak considers a leak. Running this code will raise an `AssertionError` at the end of the `async with LeakDetector():` block."},"warnings":[{"fix":"Update usage from `@no_event_loop_blocking` or `no_event_loop_blocking()` to `async with no_event_loop_blocking():`.","message":"`no_event_loop_blocking` API changed from decorator/function to an async context manager.","severity":"breaking","affected_versions":">=0.2.0"},{"fix":"Run your application with `asyncio.run(main(), debug=True)` or set the `PYTHONASYNCIODEBUG` environment variable to `1`.","message":"For best results and detailed stack traces when detecting asyncio leaks or blocking, it is recommended to enable asyncio debug mode.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all asyncio tasks, threads, and resources are correctly cleaned up or awaited before the `LeakDetector` context exits. For intentional long-lived tasks, consider using `pyleak.set_allow_extra_tasks` for specific test scenarios, though this should be used cautiously.","message":"Using `LeakDetector` without properly shutting down or cancelling all expected long-running background tasks will result in false positives (AssertionError).","severity":"gotcha","affected_versions":"All versions"},{"fix":"Upgrade pyleak to version 0.1.16 or newer to benefit from fixes addressing false positives in `CombinedLeakDetector`.","message":"`CombinedLeakDetector` in versions prior to 0.1.16 could lead to false positive warnings.","severity":"gotcha","affected_versions":"<0.1.16"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"As of v0.2.0, `no_event_loop_blocking` must be used as an `async with` context manager. Change `@no_event_loop_blocking` or `no_event_loop_blocking()` to `async with no_event_loop_blocking():`.","cause":"Attempting to use `no_event_loop_blocking` as a decorator or regular function call after v0.2.0.","error":"TypeError: object async_generator_wrapper can't be used in 'await' expression"},{"fix":"Review your application code to ensure all asyncio tasks are properly awaited or cancelled, all threads are joined, and all resources are closed before the `LeakDetector` context exits. If a task is intentionally long-lived during a test, consider allowing it explicitly, but this is generally discouraged for leak detection.","cause":"Pyleak has identified uncompleted asyncio tasks, unjoined threads, or unclosed event loops when its detector context manager exited.","error":"AssertionError: Leaks detected: X asyncio tasks"},{"fix":"Ensure that code using `no_event_loop_blocking` is part of an `async` function and is executed by an active asyncio event loop, typically by calling `asyncio.run()` or `loop.run_until_complete()`.","cause":"The `no_event_loop_blocking` context manager was called from a synchronous function or outside an active asyncio event loop.","error":"RuntimeError: no_event_loop_blocking must be used within an asyncio event loop."},{"fix":"Enable asyncio debugging by running your application with `asyncio.run(main(), debug=True)` or by setting the environment variable `PYTHONASYNCIODEBUG=1`.","cause":"Asyncio's default debugging mode is disabled, which can limit the fidelity of stack traces and the accuracy of leak detection.","error":"Leaks are not being detected, even though I suspect they exist."}]}