python访问unc路径失败的根本原因是windows会话隔离导致网络驱动器映射不可见,尤其在服务、计划任务或pyinstaller打包场景下;需用win32wnet显式连接或pysmb直连,并注意smb协议版本、认证方式及连接上下文管理。

os.path.exists 返回 False、open() 报 FileNotFoundError、甚至 os.listdir() 突然失效——这不是你代码写错了,而是 Windows 网络驱动器映射本身在 Python 运行时上下文中“不可见”或“已断开”,尤其在非交互式场景下(如服务、定时任务、PyInstaller 打包后)几乎必然发生。
根本原因不是权限,也不是路径拼错,而是:Python 无法继承或感知用户会话外的网络连接状态。映射的驱动器(如 Z:)只对当前登录用户的图形会话有效,而 Python 脚本若以服务、后台进程、计划任务方式运行,它运行在另一个会话中,Z: 对它而言根本不存在。
为什么 net use Z: \servershare 在命令行成功,但 Python 里却找不到?
因为 net use 命令默认在当前命令行会话中建立映射,而 Python 启动的子进程(比如用 subprocess.run 调用)可能运行在不同会话层级;更重要的是,即使你在脚本开头执行了 net use,后续的 os 操作仍可能因会话隔离无法识别该映射。
- Windows 服务账户(如
LocalSystem或NetworkService)压根不加载用户配置文件,net use映射对其完全无效 - 计划任务若未勾选“不管用户是否登录都要运行”,则任务运行时没有 GUI 会话,
Z:不会被挂载 - PyInstaller 打包后的 exe 默认以“无控制台”模式启动,也常触发会话隔离问题
- 调用
win32wnet.WNetAddConnection2()成功后,必须确保后续所有文件操作都在同一 Python 进程内完成——跨进程(如另起一个subprocess)会丢失上下文
win32wnet.WNetAddConnection2() 映射后仍报错“系统找不到指定的路径”
常见于以下情况:
- 没传
username和password,且目标服务器未启用“匿名访问”或“空会话”(多数现代 Windows Server 默认禁用) - 用了错误的
resource格式,例如写成"\servershare"(末尾斜杠)或"\\server\share"(多余反斜杠),正确应为r"\servershare" - 服务器启用了 SMB 签名强制策略,但本地组策略未同步开启,导致连接被静默拒绝(此时
WNetAddConnection2返回 0 但实际失败,需查 Windows 事件查看器中Microsoft-Windows-SMBClient/Connectivity日志) - 映射成功但未等待足够时间(尤其首次连接),立即调用
os.listdir("Z:\")可能因延迟返回空或报错,建议加time.sleep(0.5)或轮询验证
用 pysmb 直连 UNC 路径时反复超时或连接被重置
pysmb 绕过了 Windows API,但也因此失去系统级 SMB 配置继承(如签名策略、加密开关、DNS 解析缓存),容易在企业环境中失败:
- 默认只支持 SMBv1/v2,若服务器已禁用 SMBv1(Windows 10/Server 2016+ 默认),且未显式设置
smb_conn = SMBConnection(..., smb_model=2),连接将失败 - 未设置
use_ntlm_v2=True且服务器要求 NTLMv2 认证时,会返回NotConnectedError或空响应 - 未指定
is_direct_tcp=True时,pysmb尝试 NetBIOS 名称解析,若 DNS 或 WINS 不可用,就会卡在 DNS 查询上(表现就是超时) - 连接对象是单次会话,不能复用;频繁新建
SMBConnection实例易触发服务器连接数限制,建议复用实例并手动调用close()
真正麻烦的地方不在怎么连,而在什么时候连、谁来连、连完谁来管。同一个 UNC 路径,在用户桌面双击打开没问题,用 Python 脚本读就失败;今天能跑通,重启后又断——这些都不是偶然,是 Windows 会话模型和 SMB 协议栈在底层做的取舍。你得先判断:脚本运行在哪种上下文里,再决定是硬映射盘符、走 UNC + win32wnet、还是彻底切换到 pysmb 并自行处理认证与重连。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











