{"id":5373,"library":"portend","title":"Portend","description":"Portend is a Python library for TCP port monitoring and discovery. It provides routines to wait for a port to become free or occupied, check the current state of a port, or identify a suitable port available for binding locally. The library is currently at version 3.2.1 and is actively maintained with a stable release cadence.","status":"active","version":"3.2.1","language":"en","source_language":"en","source_url":"https://github.com/jaraco/portend","tags":["network","tcp","port","monitoring","utilities","async"],"install":[{"cmd":"pip install portend","lang":"bash","label":"Install with pip"}],"dependencies":[{"reason":"Provides Python objects and routines pertaining to date and time, used internally by portend.","package":"tempora","optional":false}],"imports":[{"note":"Most functionality is accessed directly via the 'portend' module, e.g., 'portend.occupied()'.","symbol":"portend","correct":"import portend"}],"quickstart":{"code":"import portend\nimport socket\nimport time\n\ndef demo_port_usage():\n    # Example: Wait for an occupied port (e.g., a simple server)\n    # Start a dummy server in a separate thread/process for this to work\n    # For demonstration, we'll simulate a server binding/unbinding\n\n    # Find a free port\n    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    s.bind(('localhost', 0))\n    port = s.getsockname()[1]\n    s.close()\n    print(f\"Found a free port: {port}\")\n\n    # Simulate a process binding to the port\n    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    server_socket.bind(('localhost', port))\n    server_socket.listen(1)\n    print(f\"Server bound to localhost:{port}\")\n\n    # Use portend to wait for the port to be occupied\n    print(f\"Waiting for localhost:{port} to be occupied (max 5s)...\")\n    try:\n        portend.occupied('localhost', port, timeout=5)\n        print(f\"Success: localhost:{port} is occupied.\")\n    except portend.Timeout: # Removed the direct import for Timeout as it's an attribute of portend module and was causing an error.\n        print(f\"Error: Timeout waiting for localhost:{port} to be occupied.\")\n    finally:\n        server_socket.close()\n        print(f\"Server unbound from localhost:{port}\")\n\n    # Use portend to wait for the port to be free\n    print(f\"Waiting for localhost:{port} to be free (max 5s)...\")\n    try:\n        portend.free('localhost', port, timeout=5)\n        print(f\"Success: localhost:{port} is free.\")\n    except portend.Timeout:\n        print(f\"Error: Timeout waiting for localhost:{port} to be free.\")\n\ndemo_port_usage()","lang":"python","description":"This quickstart demonstrates how to use `portend.occupied` to wait for a port to become active and `portend.free` to wait for a port to be released. It includes a simple simulation of a server binding and unbinding a port."},"warnings":[{"fix":"Check the exit code (e.g., `$?` in bash) after execution, or use the library programmatically in Python for more granular error handling.","message":"When running `portend` directly as a module (e.g., `python -m portend localhost:8080 occupied`), it exits with a status of 0 on success and 1 on failure. This is standard for command-line tools but important to note for scripting.","severity":"gotcha","affected_versions":">=1.2.0"},{"fix":"Wrap calls to `portend.assert_free()` in a `try...except portend.PortNotFree` block to handle cases where the port is not free as expected.","message":"The `portend.assert_free()` function will raise a `portend.PortNotFree` exception if the specified host/port combination is already occupied by a bound listener. Ensure proper exception handling if you intend to assert a port's availability.","severity":"gotcha","affected_versions":">=1.2.0"},{"fix":"Always use the documented functions and methods directly from the `portend` module, such as `portend.occupied` and `portend.free`.","message":"In older versions (specifically v1.2), there were 'original names' that were kept as aliases. While the current primary API (`portend.occupied`, `portend.free`, etc.) appears stable, relying on undocumented or historical aliases might lead to issues in future major versions.","severity":"deprecated","affected_versions":"<=1.2.x"},{"fix":"Review the brief release notes for version 3.0.0 and subsequent releases on GitHub (github.com/jaraco/portend/releases) for any subtle changes, although none appear to impact the core usage patterns. Ensure `tempora` is installed as a dependency.","message":"No significant breaking changes for the core `portend` API (like `portend.occupied` or `portend.free`) between v2 and v3 are explicitly documented in the official GitHub repository or PyPI project description. Users migrating across these major versions are unlikely to encounter API breakage for core functionalities, but should review the release notes for any minor adjustments or behavioral changes.","severity":"breaking","affected_versions":"3.0.0"}],"env_vars":null,"last_verified":"2026-04-13T00:00:00.000Z","next_check":"2026-07-12T00:00:00.000Z"}