macOS下uv管理的Python无法创建Socket:能否给解释器签名?
问题:macOS上uv管理的Python无法通过Socket连接目标主机,系统Python/root运行正常
问题背景
使用LetsEncrypt和Nginx Proxy Manager配置了SSL域名(例如host.mydomain.com),浏览器访问https://host.mydomain.com完全正常,但在macOS 14.4上运行ansible、esphome这类依赖socket模块的Python包时,与主机通信失败。
排查现象
普通用户用uv管理的Python运行Socket连接命令报错,root身份或系统自带Python则正常:
❯ uv run python -c 'import socket; s = socket.socket(); s.connect(("host.mydomain.com", 443)); print("Ok")' Traceback (most recent call last): File "<string>", line 1, in <module> import socket; s = socket.socket(); s.connect(("host.mydomain.com", 443)); print("Ok") ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ OSError: [Errno 65] No route to host ❯ /usr/bin/python3 -c 'import socket; s = socket.socket(); s.connect(("host.mydomain.com", 443)); print("Ok")' Ok ❯ sudo uv run python -c 'import socket; s = socket.socket(); s.connect(("host.mydomain.com", 443)); print("Ok")' Ok ❯ uv run python --version Python 3.13.13 ❯ /usr/bin/python3 --version Python 3.9.6
我的推测与尝试
推测macOS因系统Python已签名而给予特殊权限,尝试给uv管理的Python解释器签名但未成功:
❯ codesign --sign - --force --preserve-metadata=entitlements,identifier $(readlink -f .venv/bin/python)
疑问
- 是否可以通过给uv管理的Python签名解决Socket连接问题?
- 如果签名不是解决方案,还有其他办法吗?
解决方案
一、正确的代码签名步骤(针对uv的Python)
直接用--sign -生成的自签名证书不被macOS隐私机制认可,需用带网络权限的签名流程:
- 打开「钥匙串访问」,创建一个「代码签名」类型的自签名证书(或使用Apple开发者账号证书),记录证书名称(例如
My Code Sign Cert)。 - 创建权限配置文件
entitlements.plist,添加网络访问权限:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.network.client</key> <true/> </dict> </plist> - 执行签名命令,替换证书名称为你创建的证书:
codesign --sign "My Code Sign Cert" --force --entitlements entitlements.plist --preserve-metadata=identifier,entitlements $(readlink -f .venv/bin/python) - 签名完成后,进入「系统设置」→「隐私与安全性」,确认该Python解释器的网络访问权限已被允许。
二、绕过签名限制的替代方法
如果签名流程繁琐,可尝试以下方案:
- 修改防火墙规则:进入「系统设置」→「网络」→「防火墙」→「选项」,添加uv管理的Python解释器(
.venv/bin/python),允许其网络连接。 - 切换到系统Python虚拟环境:放弃uv,直接用系统Python创建虚拟环境:
/usr/bin/python3 -m venv myenv source myenv/bin/activate pip install ansible esphome - 手动配置hosts解析:若存在域名解析差异,将目标域名与对应IP写入
/etc/hosts:sudo echo "192.168.x.x host.mydomain.com" >> /etc/hosts - 检查隐私权限:进入「系统设置」→「隐私与安全性」,确保终端(或使用的Shell)拥有「完全磁盘访问」权限,同时确认uv的Python已被授予网络访问权限。
内容的提问来源于stack exchange,提问作者big_gie
相关产品推荐
相关产品推荐

