[uv][pocoui] macOS 安装与 UnityPoco 远程连接
在 macOS arm64 上用 uv 安装 pocoui 并运行 Unity 自动化脚本时,遇到依赖解析失败、win32api 缺失、以及 NoDeviceError 等问题。以下为排查结论与推荐写法。
1. uv add pocoui 失败:pywin32 无 macOS wheel
现象
uv add pocoui
# error: Distribution `pywin32==312` can't be installed because it doesn't have a source distribution or wheel for the current platform
# hint: You're on macOS (`macosx_15_0_arm64`), but `pywin32` only has wheels for: win32, win_amd64, win_arm64
原因
pocoui → airtest 在 requires_dist 里声明了 pywin32、pywinauto,但没有平台标记。这两个包只有 Windows wheel,uv 在 macOS 上解析会直接失败。
修复
在 pyproject.toml 里用 tool.uv.dependency-metadata 覆盖 airtest 的元数据,给 Windows-only 依赖加上 sys_platform == 'win32':
[[tool.uv.dependency-metadata]]
name = "airtest"
version = "1.4.3"
requires-dist = [
"Jinja2>=2.8",
"Pillow>=3.4.0",
"requests>=2.11.1",
"six<=1.16.0,>=1.9.0",
"mss==6.1.0",
"numpy<2.0",
"opencv-contrib-python<=4.6.0.66,>=4.4.0.46",
"facebook-wda==1.5.0",
"pywinauto==0.6.3; sys_platform == 'win32'",
"filelock",
"ffmpeg-python",
"tidevice",
"psutil",
"packaging",
"pywin32; sys_platform == 'win32'",
]
然后:
Windows 上仍会正常安装 pywin32 / pywinauto;macOS 上跳过即可。
2. uv run tmp.py 失败:ModuleNotFoundError: win32api
现象
poco = UnityPoco('192.168.1.6', 5001)
报错栈指向 UnityEditorWindow() → connect_device("Windows://...") → import win32api。
原因
UnityPoco 构造函数签名是:
def __init__(self, addr=DEFAULT_ADDR, unity_editor=False, connect_default_device=True, device=None, **options):
错误写法把 5001 传给了第二个参数 unity_editor。5001 为 truthy,于是走了 Unity Editor on Windows 分支,在 macOS 上必然失败。
修复
地址必须是一个 (ip, port) 元组:
poco = UnityPoco(('192.168.1.6', 5001))
3. uv run tmp.py 失败:NoDeviceError: 'No devices added.'
现象
修正地址写法后:
poco = UnityPoco(('192.168.1.6', 5001))
# airtest.core.error.NoDeviceError: 'No devices added.'
原因
UnityPoco.__init__ 在非 editor 模式下会执行:
dev = device or current_device()
current_device() 在没有已连接 airtest 设备时直接抛异常,而不是返回 None。
但底层 StdPoco 在传入非 localhost 的 ip 时,会跳过整个 device 分支,仅通过 TCP 连接 (ip, port) 获取 UI 树。也就是说:对纯网络远程 Unity 游戏,airtest device 在连接阶段并非必需,却被 UnityPoco 提前检查了。
输入路径的区别
| 模式 |
输入实现 |
是否需要 airtest device |
默认 use_airtest_input=True |
AirtestInput |
是(touch()、get_current_resolution() 等) |
use_airtest_input=False |
StdInput |
否(通过 RPC 调用 Click / Swipe 等) |
若游戏在远端、脚本在 macOS 上只通过 Poco SDK 协议操控 UI,应使用 SDK 侧输入(RPC),而不是 airtest 本地触控。
推荐写法(远程 Unity,无本地 Android/iOS 设备)
from poco.drivers.unity3d import UnityPoco
poco = UnityPoco(
('192.168.1.6', 5001),
connect_default_device=False,
use_airtest_input=False,
)
poco("Canvas").click()
说明:
connect_default_device=False:避免 fallback 到 connect_device("Android:///")
use_airtest_input=False:点击走 StdInput,经 TCP RPC 发到游戏端
- 仍需显式传入
device=... 或 patch 掉 current_device() 调用,因为 UnityPoco 当前实现会在构造时访问 current_device()
若本地有 Android 设备且游戏跑在手机上,更常见的写法是:
from airtest.core.api import connect_device
from poco.drivers.unity3d import UnityPoco
dev = connect_device("Android:///")
poco = UnityPoco((ip, 5001), device=dev)
4. API 速查
# 错误:5001 被当成 unity_editor=True
UnityPoco('192.168.1.6', 5001)
# 正确:addr 是 (ip, port) 元组
UnityPoco(('192.168.1.6', 5001))
# Unity Editor(仅 Windows)
UnityPoco(('localhost', 5001), unity_editor=True)
# 默认无参:尝试连默认 Android 设备 + localhost:5001
UnityPoco()
推荐组合
- macOS 安装依赖:
pyproject.toml 里加 tool.uv.dependency-metadata 覆盖 airtest 的 Windows-only 依赖。
- 远程 Unity 自动化:
UnityPoco(('ip', port), connect_default_device=False, use_airtest_input=False),并确保构造时不触发 current_device()(传 device 或按需 wrapper)。
- 本地 Android Unity:先
connect_device("Android:///"),再 UnityPoco((ip, 5001), device=dev)。
[uv][pocoui] macOS 安装与 UnityPoco 远程连接
1.
uv add pocoui失败:pywin32 无 macOS wheel现象
原因
pocoui→airtest在requires_dist里声明了pywin32、pywinauto,但没有平台标记。这两个包只有 Windows wheel,uv 在 macOS 上解析会直接失败。修复
在
pyproject.toml里用tool.uv.dependency-metadata覆盖airtest的元数据,给 Windows-only 依赖加上sys_platform == 'win32':然后:
Windows 上仍会正常安装
pywin32/pywinauto;macOS 上跳过即可。2.
uv run tmp.py失败:ModuleNotFoundError: win32api现象
报错栈指向
UnityEditorWindow()→connect_device("Windows://...")→import win32api。原因
UnityPoco构造函数签名是:错误写法把
5001传给了第二个参数unity_editor。5001为 truthy,于是走了 Unity Editor on Windows 分支,在 macOS 上必然失败。修复
地址必须是一个
(ip, port)元组:3.
uv run tmp.py失败:NoDeviceError: 'No devices added.'现象
修正地址写法后:
原因
UnityPoco.__init__在非 editor 模式下会执行:current_device()在没有已连接 airtest 设备时直接抛异常,而不是返回None。但底层
StdPoco在传入非localhost的ip时,会跳过整个 device 分支,仅通过 TCP 连接(ip, port)获取 UI 树。也就是说:对纯网络远程 Unity 游戏,airtest device 在连接阶段并非必需,却被UnityPoco提前检查了。输入路径的区别
use_airtest_input=TrueAirtestInputtouch()、get_current_resolution()等)use_airtest_input=FalseStdInputClick/Swipe等)若游戏在远端、脚本在 macOS 上只通过 Poco SDK 协议操控 UI,应使用 SDK 侧输入(RPC),而不是 airtest 本地触控。
推荐写法(远程 Unity,无本地 Android/iOS 设备)
说明:
connect_default_device=False:避免 fallback 到connect_device("Android:///")use_airtest_input=False:点击走StdInput,经 TCP RPC 发到游戏端device=...或 patch 掉current_device()调用,因为UnityPoco当前实现会在构造时访问current_device()若本地有 Android 设备且游戏跑在手机上,更常见的写法是:
4. API 速查
推荐组合
pyproject.toml里加tool.uv.dependency-metadata覆盖airtest的 Windows-only 依赖。UnityPoco(('ip', port), connect_default_device=False, use_airtest_input=False),并确保构造时不触发current_device()(传device或按需 wrapper)。connect_device("Android:///"),再UnityPoco((ip, 5001), device=dev)。