port-for: Local TCP Ports Management
Port-for is a utility that assists with local TCP ports management. It can identify an unused TCP localhost port and maintain an association with a given identifier, ensuring that subsequent requests for the same ID return the same port number. The current version is 1.0.0, primarily functioning as a local port management tool.
Common errors
-
ModuleNotFoundError: No module named 'port_for'
cause The 'port-for' library is not installed in your Python environment, or there is a typo in the import statement, or your script file is named 'port_for.py' which shadows the actual module.fixInstall the library using pip: `pip install port-for`. If a typo, correct the import to `import port_for`. If shadowing, rename your script file. -
AttributeError: module 'port_for' has no attribute 'some_non_existent_method'
cause You are trying to call a method or access an attribute that does not exist in the 'port_for' module (e.g., a typo in the function name) or has been removed/renamed in the version you are using. For example, 'get_available_port' was deprecated in favor of 'available_local_port' with a 'binding' argument.fixConsult the `port-for` documentation for the correct function names and their usage. For finding an available port, use `port_for.available_local_port()`. -
OSError: [Errno 98] Address already in use
cause The underlying operating system reports that the port 'port-for' attempted to bind is already in use by another process. While `port-for` aims to find available ports, this can occur if you explicitly request a port that is occupied, or due to a race condition where another process claims the port between `port-for`'s check and its attempt to bind.fixAllow `port-for` to select a random available port by calling `port_for.available_local_port()` without the `port` argument. If you need a specific port, ensure no other application is using it, or use `netstat` (or `lsof` on Linux/macOS) to identify and stop the conflicting process. -
TypeError: available_local_port() got an unexpected keyword argument 'id'
cause You are attempting to use the `id` keyword argument with the `available_local_port` function. The `id` argument was part of the deprecated `get_available_port` function and has been replaced by the `binding` argument in `available_local_port`.fixReplace the `id` argument with `binding`. For example, change `port_for.available_local_port(id='my_service')` to `port_for.available_local_port(binding='my_service')`.
Warnings
- gotcha The `PortFor` class is designed for *persistent* port assignments tied to an identifier, not for finding a random available port each time. If you need a new, unassociated port, you must use a new ID or `available_ports`.
- gotcha While `port-for` aims to manage local port persistence, in highly concurrent multi-process environments, there's a theoretical race condition when *initially* assigning a port for a new ID. If multiple processes simultaneously attempt to call `forward_port` with the *same new ID* for the very first time, careful synchronization might be required externally, as `port-for` primarily handles persistence within a single management context.
- gotcha The `forward_port` method takes a `default_port` argument. This is a *suggestion* for the desired port, not a guarantee. If the `default_port` is already in use (or was assigned to another ID), `port-for` will find another available port. The returned port is what's assigned to the ID.
Install
-
pip install port-for
Imports
- available_ports
from port_for import available_ports
- PortFor
from port_for import PortFor
Quickstart
from port_for import available_ports, PortFor
# Find an ephemeral available port (context manager ensures release)
with available_ports(5000) as port:
print(f"Found available port (5000 or next): {port}")
# Use PortFor for persistent port assignment based on an ID
port_manager = PortFor()
# Assign a port for 'my-service' (will try 8000 first)
my_service_port = port_manager.forward_port("my-service", 8000)
print(f"Assigned port for 'my-service': {my_service_port}")
# Assign a port for 'another-service' (will try 9000 first)
another_service_port = port_manager.forward_port("another-service", 9000)
print(f"Assigned port for 'another-service': {another_service_port}")
# Subsequent calls with the same ID will return the same assigned port
same_service_port = port_manager.forward_port("my-service", 8000) # 8000 is a suggestion, not a requirement
print(f"Re-requested port for 'my-service' (should be {my_service_port}): {same_service_port}")
# To release a port (optional, happens on process exit by default)
port_manager.release("another-service")
print("Released port for 'another-service'")