Return a port that claim_port can claim right
now, on every address that localhost can mean on this machine.
The port isn't held after it's returned, so another program can take it before you
use it. Use free_port in tests and local tools, not to choose a port for a server
that other programs depend on.
Returns:
| Type |
Description |
int
|
A port that can be claimed right now.
|
Raises:
| Type |
Description |
OSError
|
When none of the ports tried can be claimed, or when a port can't be
found for any other reason.
|
Examples:
port = free_port()
with claim_port(port) as claimed:
for sock in claimed.sockets:
sock.listen()
Source code in src/notwork/free_port.py
| def free_port() -> int:
"""
Return a port that [`claim_port`][notwork.claim_port.claim_port] can claim right
now, on every address that `localhost` can mean on this machine.
The port isn't held after it's returned, so another program can take it before you
use it. Use `free_port` in tests and local tools, not to choose a port for a server
that other programs depend on.
Returns:
A port that can be claimed right now.
Raises:
OSError: When none of the ports tried can be claimed, or when a port can't be
found for any other reason.
Examples:
```python
port = free_port()
with claim_port(port) as claimed:
for sock in claimed.sockets:
sock.listen()
```
"""
for _ in range(_ATTEMPTS):
with socket(AF_INET, SOCK_STREAM) as sock:
sock.bind(("127.0.0.1", 0))
port: int = sock.getsockname()[1]
try:
claim_port(port).close()
except PortInUseError:
continue
return port
raise OSError(
EADDRINUSE,
f"No free port found in {_ATTEMPTS} attempts",
)
|