“UnBind” -- frees occupied ports by detecting and unbinding blocking processes
Project description
ub
"UnBind" - Frees occupied ports by detecting and unbinding blocking processes.
Never struggle with "port already in use" errors again! ub automatically detects what's using your ports, shows you the processes with their PIDs, and gives you options to kill them or find alternative ports.
🚀 Installation
pip install ub
✨ Quick Start
For FastAPI/Uvicorn servers:
from fastapi import FastAPI
from ub import start_uvicorn_with_port_handling
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
# This will handle port conflicts automatically
start_uvicorn_with_port_handling(app, host="0.0.0.0", port=8000, reload=True)
For Flask servers:
from flask import Flask
from ub import start_flask_with_port_handling
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
# This will handle port conflicts automatically
start_flask_with_port_handling(app, host="0.0.0.0", port=5000, debug=True)
For any server:
from ub import start_server_with_port_handling
import uvicorn
def my_server_starter(host, port, **kwargs):
# Your server startup logic here
uvicorn.run(my_app, host=host, port=port, **kwargs)
start_server_with_port_handling(
my_server_starter,
host="0.0.0.0",
port=8000,
service_name="My Custom Server"
)
🎭 Context Managers
ub now provides powerful context managers for automatic port management and server lifecycle control:
Basic Port Management
from ub import port_context
with port_context("0.0.0.0", 8000, "My API") as port:
# Port conflict automatically resolved
uvicorn.run(app, host="0.0.0.0", port=port)
# Automatic cleanup on exit
Managed Server Lifecycle
from ub import managed_server
def my_server(host, port, app):
uvicorn.run(app, host=host, port=port)
with managed_server(my_server, port=8000, app=my_app) as port:
print(f"Server running on port {port}")
# Do other work while server runs
time.sleep(10)
# Server automatically shut down here
Framework-Specific Context Managers
# FastAPI
from ub import fastapi_context
with fastapi_context(app, port=8000, reload=True) as port:
print(f"FastAPI running on port {port}")
# Server runs in background, auto-cleanup on exit
# Flask
from ub import flask_context
with flask_context(app, port=5000, debug=True) as port:
print(f"Flask running on port {port}")
# Server runs in background, auto-cleanup on exit
Port Reservation
from ub import reserve_port
# Reserve multiple consecutive ports
with reserve_port("0.0.0.0", 8000, count=3) as ports:
print(f"Reserved ports: {ports}") # e.g., [8000, 8001, 8002]
start_service_1(port=ports[0])
start_service_2(port=ports[1])
start_service_3(port=ports[2])
# Ports automatically released
Temporary Process Management
from ub import temporary_kill
# Temporarily clear a port
with temporary_kill(8000) as killed_processes:
print(f"Temporarily killed {len(killed_processes)} processes")
# Port 8000 is now free for your use
start_my_server(port=8000)
# Processes info available, optional restoration
🔧 What It Does
When you try to start a server and the port is already in use, ub will:
- Detect the conflict - Immediately identifies when a port is occupied
- Show process details - Lists all processes using the port with PIDs, names, and full command lines
- Offer clear options:
- Kill the conflicting processes
- Find and use an alternative port
- Exit gracefully
Example interaction:
🚨 Port 8000 is already in use!
Processes using port 8000:
--------------------------------------------------------------------------------
1. PID: 1234 | Name: python
Command: python my_old_server.py
2. PID: 5678 | Name: node
Command: node server.js
What would you like to do for FastAPI Server?
1. Kill the conflicting process(es)
2. Use a different port
3. Exit
Enter your choice (1-3):
📚 API Reference
Core Functions
handle_port_conflict(host, port, service_name=None)
Handles port conflicts interactively. Returns the port to use (either original after cleanup or a new one).
from ub import handle_port_conflict
port = handle_port_conflict("0.0.0.0", 8000, "My API")
# Now use 'port' to start your server
check_port_available(host, port)
Check if a port is available.
from ub import check_port_available
if check_port_available("localhost", 8000):
print("Port 8000 is free!")
get_processes_using_port(port)
Get detailed information about processes using a port.
from ub import get_processes_using_port
processes = get_processes_using_port(8000)
for proc in processes:
print(f"PID: {proc['pid']}, Name: {proc['name']}, Command: {proc['command']}")
find_available_port(start_port, host="0.0.0.0", max_attempts=100)
Find the next available port starting from a given port.
from ub import find_available_port
available_port = find_available_port(8000)
print(f"Next available port: {available_port}")
Convenience Wrappers
start_uvicorn_with_port_handling(app, host="0.0.0.0", port=8000, **kwargs)
Start a Uvicorn/FastAPI server with automatic port conflict handling.
start_flask_with_port_handling(app, host="0.0.0.0", port=5000, **kwargs)
Start a Flask server with automatic port conflict handling.
start_server_with_port_handling(server_func, host="0.0.0.0", port=8000, service_name=None, **server_kwargs)
Generic wrapper for any server startup function.
Context Managers
port_context(host="0.0.0.0", port=8000, service_name=None, auto_kill=False)
Context manager for handling port conflicts. Yields the port to use.
from ub import port_context
with port_context("0.0.0.0", 8000, "My API", auto_kill=True) as port:
uvicorn.run(app, host="0.0.0.0", port=port)
managed_server(server_func, host="0.0.0.0", port=8000, service_name=None, auto_kill=False, **server_kwargs)
Context manager that starts a server and ensures cleanup. Yields the port number.
fastapi_context(app, host="0.0.0.0", port=8000, auto_kill=False, **uvicorn_kwargs)
Context manager specifically for FastAPI applications.
flask_context(app, host="0.0.0.0", port=5000, auto_kill=False, **flask_kwargs)
Context manager specifically for Flask applications.
reserve_port(host="0.0.0.0", start_port=8000, count=1)
Context manager to reserve consecutive ports. Yields list of reserved port numbers.
temporary_kill(port, restore=False)
Context manager to temporarily kill processes using a port. Yields list of killed process info.
🎯 Usage Patterns
Pattern 1: Drop-in replacement (Recommended)
Replace your existing server startup with the ub equivalent:
# Before
uvicorn.run(app, host="0.0.0.0", port=8000)
# After
from ub import start_uvicorn_with_port_handling
start_uvicorn_with_port_handling(app, host="0.0.0.0", port=8000)
Pattern 2: Manual conflict handling
Handle conflicts yourself with full control:
from ub import handle_port_conflict
import uvicorn
desired_port = 8000
final_port = handle_port_conflict("0.0.0.0", desired_port, "My Custom API")
print(f"Starting server on port {final_port}")
uvicorn.run(app, host="0.0.0.0", port=final_port)
Pattern 3: Port checking utilities
Use individual utility functions:
from ub import check_port_available, get_processes_using_port, find_available_port
port = 8000
if not check_port_available("localhost", port):
print(f"Port {port} is busy!")
# See what's using it
processes = get_processes_using_port(port)
for proc in processes:
print(f"Process: {proc['name']} (PID: {proc['pid']})")
# Find alternative
alt_port = find_available_port(port + 1)
print(f"Try port {alt_port} instead")
Pattern 4: Custom server integration
Integrate with any server framework:
from ub import start_server_with_port_handling
import http.server
import socketserver
def start_simple_server(host="0.0.0.0", port=8080):
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer((host, port), Handler) as httpd:
print(f"Serving at http://{host}:{port}")
httpd.serve_forever()
start_server_with_port_handling(
start_simple_server,
host="0.0.0.0",
port=8080,
service_name="Simple HTTP Server"
)
Pattern 5: Context manager for testing
Perfect for tests that need temporary servers:
from ub import fastapi_context
def test_my_api():
with fastapi_context(my_app, auto_kill=True) as port:
# Server runs in background with auto-cleanup
response = requests.get(f"http://localhost:{port}/health")
assert response.status_code == 200
# Server automatically cleaned up after test
Pattern 6: Multi-service development
Run multiple services with automatic port management:
from ub import reserve_port, fastapi_context
with reserve_port(start_port=8000, count=3) as ports:
with fastapi_context(auth_service, port=ports[0]) as auth_port:
with fastapi_context(api_service, port=ports[1]) as api_port:
with fastapi_context(ui_service, port=ports[2]) as ui_port:
# All services running, do integration work
run_integration_tests(auth_port, api_port, ui_port)
# All services automatically cleaned up
🌍 Cross-Platform Support
ub works seamlessly across platforms:
- macOS/Linux: Uses
lsofandpsfor detailed process information - Windows: Uses
netstatandtasklistfor process detection - Fallbacks: Gracefully handles missing system tools
🔐 Process Management
When killing processes, ub:
- Tries graceful termination first (
SIGTERMon Unix, standard termination on Windows) - Falls back to force kill if needed (
SIGKILLon Unix,/Fflag on Windows) - Waits and verifies process termination
- Reports success/failure clearly
⚡ Benefits
- 🚫 No more "address already in use" mysteries - See exactly what's blocking your port
- ⚡ One-click process cleanup - Kill conflicting processes safely with a single choice
- 🔄 Automatic port discovery - Find alternative ports instantly
- 🔧 Framework agnostic - Works with FastAPI, Flask, Django, custom servers, anything
- 🖥️ Cross-platform - Same experience on macOS, Linux, and Windows
- 👥 User-friendly - Clear messages, safe defaults, graceful error handling
- 📦 Zero dependencies - Uses only Python standard library
- 🎭 Context manager support - Automatic cleanup and resource management
- 🧪 Perfect for testing - Temporary servers with guaranteed cleanup
- 🔄 Exception safe - Resources properly released even when errors occur
🤝 Contributing
Issues and pull requests welcome! This tool aims to eliminate the frustration of port conflicts for all developers.
📄 License
MIT License - Use freely in your projects!
Stop fighting port conflicts. Start using ub. 🎯
“UnBind”: Frees occupied ports by detecting and unbinding blocking processes.
To install: pip install ub
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ub-0.0.10.tar.gz.
File metadata
- Download URL: ub-0.0.10.tar.gz
- Upload date:
- Size: 15.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
caaf684c041db0da85bf5fb31eaa2dab672bbd558d362789e7ddf111d9974271
|
|
| MD5 |
4e2b8a132a42ad0624b6de651017b830
|
|
| BLAKE2b-256 |
6702b11d103cf8140cc8427f80ae23dc8061d66859d4aeb4f20c93e826fe6656
|
File details
Details for the file ub-0.0.10-py3-none-any.whl.
File metadata
- Download URL: ub-0.0.10-py3-none-any.whl
- Upload date:
- Size: 13.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b66362f1dcbe179eef42ea0c3a19ffa5b69ef3cf3477356070f3db6cc391fc64
|
|
| MD5 |
06b7bf0acdd289b9b0e582a2e4de205a
|
|
| BLAKE2b-256 |
0e8c8b4cc47c0dee24996fcd604d74134712ba5327f293a5099b321b4af182d6
|