{"id":6881,"library":"simpervisor","title":"Simpervisor: Simple Async Process Supervisor","description":"Simpervisor is a lightweight Python library providing an asynchronous process supervisor. It offers the `SupervisedProcess` class to manage external processes with async methods like `start`, `ready`, `terminate`, and `kill`. The library is actively maintained, with its latest major release (1.0.0) in May 2023, indicating a stable but less frequent release cadence focused on robustness.","status":"active","version":"1.0.0","language":"en","source_language":"en","source_url":"https://github.com/jupyterhub/simpervisor","tags":["async","process","supervisor","asyncio","subprocess"],"install":[{"cmd":"pip install simpervisor","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"Required runtime environment","package":"Python","version":">=3.8"}],"imports":[{"symbol":"SupervisedProcess","correct":"from simpervisor import SupervisedProcess"}],"quickstart":{"code":"import asyncio\nimport sys\nimport os\nfrom simpervisor import SupervisedProcess\n\n# Create a dummy script to supervise\ndummy_script_content = \"\"\"\nimport asyncio\nimport sys\nimport time\n\nasync def child_process_task():\n    print(f\"Child process {os.getpid()} started.\")\n    try:\n        for i in range(5):\n            print(f\"Child process {os.getpid()}: Working... {i+1}/5\")\n            await asyncio.sleep(1)\n        print(f\"Child process {os.getpid()}: Done working, exiting.\")\n    except asyncio.CancelledError:\n        print(f\"Child process {os.getpid()}: Cancelled, cleaning up.\")\n    except Exception as e:\n        print(f\"Child process {os.getpid()}: Error - {e}\")\n    finally:\n        print(f\"Child process {os.getpid()} exiting gracefully.\")\n\nif __name__ == '__main__':\n    asyncio.run(child_process_task())\n\"\"\"\n\nasync def main():\n    script_path = \"./dummy_child_script.py\"\n    with open(script_path, \"w\") as f:\n        f.write(dummy_script_content)\n\n    print(\"Starting supervisor example...\")\n\n    # Supervise the dummy script using python as the executable\n    # This assumes 'python' is in your PATH\n    process = SupervisedProcess(\n        [sys.executable, script_path], # Command to run the child process\n        always_restart=False # For this example, don't restart automatically\n    )\n\n    await process.start()\n    print(f\"Supervisor: Process started with PID {process.pid}\")\n\n    await asyncio.sleep(2) # Give child some time to work\n\n    if await process.ready():\n        print(\"Supervisor: Child process reports ready (or has started).\")\n    else:\n        print(\"Supervisor: Child process not yet ready.\")\n\n    await asyncio.sleep(3)\n\n    print(\"Supervisor: Attempting to terminate child process...\")\n    await process.terminate()\n    # await process.wait() # Can wait for termination if needed\n\n    if not process.running:\n        print(\"Supervisor: Child process terminated.\")\n    else:\n        print(\"Supervisor: Child process is still running after terminate attempt.\")\n\n    os.remove(script_path)\n    print(\"Supervisor: Example finished.\")\n\nif __name__ == '__main__':\n    asyncio.run(main())\n","lang":"python","description":"This example demonstrates how to use `SupervisedProcess` to start an asynchronous Python script as a child process, monitor its status with `ready()`, and gracefully terminate it using `terminate()`. The child process simulates some work before exiting or being cancelled. The `sys.executable` is used to ensure the same Python interpreter runs the child script."},"warnings":[{"fix":"Remove the `loop=...` argument from `SupervisedProcess` instantiation and method calls. `simpervisor` now automatically uses `asyncio.get_running_loop()`.","message":"The `loop` argument was removed from the `SupervisedProcess` constructor and its methods (`start`, `ready`, `terminate`, `kill`) in version 1.0.0. If you were explicitly passing an `asyncio` event loop, this code will break.","severity":"breaking","affected_versions":"1.0.0 and later"},{"fix":"Thoroughly test `simpervisor` usage on Windows for your specific child processes. Consider alternative process management solutions for critical Windows deployments if issues persist.","message":"Running `SupervisedProcess` on Windows has historically encountered issues, particularly related to process termination and signal handling. While some fixes have been introduced, full cross-platform compatibility for all subprocess scenarios (especially complex ones) may not be guaranteed.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all potentially blocking operations in your `asyncio` application are properly awaited or offloaded to a thread pool using `loop.run_in_executor()`.","message":"As `simpervisor` relies on `asyncio`, blocking the event loop within your async application (e.g., by calling synchronous I/O operations without `run_in_executor`) can prevent the supervisor from properly monitoring and managing child processes, leading to unresponsive behavior.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}