Python应用经cx_freeze打包后访问网络共享文件报FileNotFoundError
解决方案:cx_freeze打包后访问UNC网络路径问题
方案1:手动转换为Windows扩展UNC路径格式
cx_freeze打包后的程序对标准UNC路径(\\foo\bar\...)兼容性较差,但支持Windows扩展UNC格式(\\?\UNC\foo\bar\...)。可以编写一个路径转换函数,自动将普通UNC路径转为扩展格式:
import os from pathlib import Path def convert_to_extended_unc(path): path_str = str(path) # 检测是否为标准UNC路径且未转为扩展格式 if path_str.startswith("\\\\") and not path_str.startswith("\\\\?\\UNC\\"): # 替换路径前缀为扩展UNC格式 extended_path = "\\\\?\\UNC\\" + path_str[2:] return Path(extended_path) return path
在业务代码中,所有涉及网络路径的操作前先做转换:
# 预处理文件列表中的路径 ListOfFiles = [convert_to_extended_unc(x) for x in ListOfFiles] # 正常获取文件大小 sizelist = [float(p.stat().st_size) for p in ListOfFiles]
测试脚本修改示例:
# encoding: utf-8 from pathlib import Path def convert_to_extended_unc(path): path_str = str(path) if path_str.startswith("\\\\") and not path_str.startswith("\\\\?\\UNC\\"): extended_path = "\\\\?\\UNC\\" + path_str[2:] return Path(extended_path) return path folder = input("Folder:") folder_path = convert_to_extended_unc(folder) file_list = [] file_list += list(folder_path.rglob("**/*.mdf")) file_list += list(folder_path.rglob("**/*.mf4")) file_list += list(folder_path.rglob("**/*.dat")) print([(p, p.is_file()) for p in file_list]) # For tracking x = input("Press enter...")
方案2:调用Windows原生API绕过标准库限制
如果方案1无效,可以直接调用Windows系统API来获取文件信息,绕过Python标准库的路径处理逻辑:
import ctypes from pathlib import Path def get_windows_file_size(path): path_str = str(path) # 定义Windows API所需的结构体 class FILETIME(ctypes.Structure): _fields_ = [("dwLowDateTime", ctypes.c_uint32), ("dwHighDateTime", ctypes.c_uint32)] class WIN32_FILE_ATTRIBUTE_DATA(ctypes.Structure): _fields_ = [("dwFileAttributes", ctypes.c_uint32), ("ftCreationTime", FILETIME), ("ftLastAccessTime", FILETIME), ("ftLastWriteTime", FILETIME), ("nFileSizeHigh", ctypes.c_uint32), ("nFileSizeLow", ctypes.c_uint32)] data = WIN32_FILE_ATTRIBUTE_DATA() # 调用API获取文件属性 success = ctypes.windll.kernel32.GetFileAttributesExW(path_str, 0, ctypes.byref(data)) if not success: raise FileNotFoundError(f"File not found: {path_str}") # 合并高低位计算文件大小 return (data.nFileSizeHigh << 32) + data.nFileSizeLow
替换原文件大小获取代码:
sizelist = [float(get_windows_file_size(x)) for x in ListOfFiles]
方案3:调整cx_freeze打包配置
在setup.py中确保路径处理相关模块被正确打包,若为GUI程序需指定base参数:
from cx_Freeze import setup, Executable executables = [Executable("your_script.py", base="Win32GUI")] # 控制台程序可省略base参数 setup( name="YourApp", version="1.0", description="Application Description", executables=executables, options={ "build_exe": { "includes": ["pathlib", "os"], "packages": ["ctypes"] # 使用方案2时需添加 } } )
内容的提问来源于stack exchange,提问作者Carles MR
相关产品推荐
相关产品推荐

