socket.connect_ex()返回0表示端口被占用(有服务监听),非0不等于空闲,需设短超时、及时关闭套接字,本地检测更可靠;定位进程需sudo lsof或netstat,time_wait状态需so_reuseaddr解决。

用 socket.connect_ex() 判断端口是否被占用
最直接的办法不是“扫描”,而是尝试连一下——connect_ex() 返回 0 表示连接成功(端口开放且有服务监听),非 0 通常意味着端口未被占用或拒绝连接。它比 connect() 安全,不会抛异常中断流程。
常见错误现象:用 connect() 写 try/except,结果在防火墙拦截、目标主机不可达时抛出 TimeoutError 或 ConnectionRefusedError,误判为“端口空闲”;其实只是连不上,不等于没被占。
- 只对
localhost或已知可达的本地 IP 使用,远程检测不准(受网络策略干扰) - 超时必须设短,否则卡住,默认阻塞可能等几十秒:
sock.settimeout(0.5) - 记得
sock.close(),尤其循环检测多个端口时,避免OSError: [Errno 24] Too many open files
示例:
import socket
def is_port_in_use(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(0.5)
result = sock.connect_ex((host, port))
sock.close()
return result == 0
<p>print(is_port_in_use('127.0.0.1', 8080)) # True 表示已被占用(有服务监听)</p>
Linux/macOS 下绕过权限限制查本机端口
socket.connect_ex() 只能告诉你“能不能连上”,但没法告诉你“谁在用”。真要定位进程,得调系统命令。普通用户无法读取所有进程的 socket 信息,所以 lsof -i :8080 或 netstat -tuln | grep :8080 常因权限失败返回空——这不是没占用,是没权限看。
- 加
sudo才能看到其他用户(包括 root)启动的服务,比如 Docker、Nginx -
lsof在 macOS 上默认可用,Linux 需先装:apt install lsof或yum install lsof - 注意
lsof -i :8080匹配的是监听地址为*:8080或127.0.0.1:8080的进程,但不匹配192.168.1.100:8080(除非显式指定)
Python 中避免 Address already in use 错误
开发时起 Flask/FastAPI 服务报这个错,大概率不是端口真被别的程序占了,而是上次运行崩溃退出,socket 还在 TIME_WAIT 状态。操作系统会保留该端口一小段时间(通常几十秒),防止旧包干扰新连接。
- 代码里加
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)可跳过等待,但仅限于你 own 的 socket(比如自己写 server) - Web 框架如 Flask 不暴露底层 socket 控制,此时只能换端口或等一会儿,硬杀进程反而可能留下僵尸 socket
- 别依赖
ps aux | grep python找残留进程——很多框架用子进程或异步模型,主进程早没了,但 worker 还占着端口
Windows 上检测更麻烦?用 netstat + findstr
Windows 没 lsof,原生命令只有 netstat -ano,输出冗长还带 PID,手动找很累。直接管道过滤最实用:
netstat -ano | findstr :8080 —— 查端口;再用 tasklist | findstr "12345"(12345 是上一步看到的 PID)查进程名。
- PowerShell 更准:
Get-NetTCPConnection -LocalPort 8080 | Select-Object -ExpandProperty OwningProcess | ForEach-Object { Get-Process -Id $_ } - 注意
netstat默认不显示监听中的 UDP 端口,加-u参数才查 UDP 占用(比如 DNS、NTP 服务) - 某些安全软件会 hook 网络栈,导致
netstat漏掉部分监听项,这时只能靠socket.connect_ex()实测
端口检测真正难的从来不是“怎么写代码”,而是区分“连不上”“被拒绝”“根本没监听”这三种状态;而多数人卡在第一步——没意识到 connect_ex() 返回值里,只有 0 能确定“有人在听”,其余都只是“暂时不通”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











