Cookbook
Practical recipes built on the portly API.
Pick a free port for a dev server
Use find_free to grab a free port, then hand it to your server. Prefer a
specific port and fall back to a free one when it is busy:
import portly
port = portly.find_free(8000)
print(f"Starting server on {port}")
To constrain the search to a known range (and reserve several ports at once):
import portly
port = portly.find_free_in_range(8000, 8100) # a single free port
ports = portly.find_free_in_range(8000, 8100, count=3) # three distinct ports
Wait for a service to come up (wait-for-it)
Block until a server is actually listening on a port — the classic deploy / compose pattern:
import portly
if portly.wait_for_server(8000, timeout=30):
print("Server is ready!")
else:
print("Server did not come up in time")
raise SystemExit(1)
Wait for a port to free up
The inverse: block until a process releases a port.
import portly
if portly.wait_until_free(5432, timeout=30):
print("Port 5432 is free")
Inspect and kill what is holding a port
import portly
info = portly.get_info(8000)
if info is not None:
print(f"pid={info['pid']} name={info['name']} cmd={info['cmd']}")
# Kill it (SIGTERM); use force=True for SIGKILL.
portly.kill(8000)
Handle errors with the typed hierarchy
import portly
from portly import PortlyError, PortlyPortError
try:
portly.find_free_in_range(1, 1)
except PortlyPortError as exc:
# Most specific type; also caught by `except OSError`.
print(f"No free port: {exc}")
except PortlyError as exc:
# Any portly failure.
print(f"portly error: {exc}")
TOCTOU
A port returned by find_free/find_free_in_range can be taken between
the check and your bind(). For a race-free reservation, bind to port 0
and let the OS choose.