Python函数整体运行触发FileNotFoundError,逐行运行正常
我写了个小程序,用来把Windows Assets文件夹里的图片复制到Pictures文件夹并重命名。逐行运行代码时一切正常,但调用pictures()函数整体运行时,会触发WinError 2 系统找不到指定文件错误,错误指向os.rename语句。单独运行这段重命名代码也没问题。
除了文件位置错误、命名错误外,还有啥原因会导致分段运行正常但整体运行异常?实在排查不出来了,逐行跑完全没问题。
编辑补充:错误提示找不到文件"0c372e060088d1ed55f9dce0bab55e11608c3c37ec32c01a6f195884cda7beb3",但这个文件不在file_list2里,对应目录也没有这个文件,就像解释器在找一个本不该存在的文件。完整代码如下:
def pictures(): # Import the necessary modules. import os import shutil from os import path import datetime import webbrowser import cv2 #Create folder in Pictures if needed. if "Desktop Backgrounds" not in os.listdir(path.expandvars(r"%HOMEPATH%\Pictures")): os.mkdir(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds")) if "New Backgrounds" not in os.listdir(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds")): os.mkdir(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds")) # Copy all files from Assets to New Backgrounds raw_list = os.listdir(path.expandvars(\ r"%LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets")) for raw in raw_list: shutil.copy(src = path.expandvars(r"%LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets\\" + raw), \ dst = path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds")) # Rename all files in New Backgrounds to a .jpeg extension & datetime to prevent existing file error. file_list2 = os.listdir(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds")) now = str(datetime.datetime.now())[19:] for index, file in enumerate(file_list2): os.rename(src = path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds\\" + file), \ dst = path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds\\" + str(index + 1) + now + ".jpeg")) # Remove all files with small dimensions. # (Continue so the none-type images aren't checked against the < 1919 if statement.) file_list3 = os.listdir(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds")) for file in file_list3: image = cv2.imread(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds\\" + file)) if type(image) == type(None): os.remove(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds\\" + file)) continue if image.shape[1] < 1919: os.remove(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds\\" + file)) else : pass # Open Windows Explorer to \New Backgrounds. webbrowser.open(path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds\New Backgrounds")) pictures()
问题根源分析
目录列表与实际文件不同步
你获取file_list2后,如果目标目录里有之前运行残留的旧文件,重命名时这些旧文件可能已经被删除或重命名,导致遍历file_list2时,某些文件已经不存在——这就是错误提示的文件不在当前目录的原因,它是之前的残留文件名。缩进错误导致逻辑混乱
原代码中file_list3的缩进错误,被嵌套在了重命名的for循环内,导致重命名过程中就去遍历目录,此时部分文件已经被重命名,后续迭代查找原文件名自然会失败。路径拼接不规范
用字符串拼接路径(比如"\\" + raw)容易因系统分隔符、字符串格式问题导致路径错误,进而触发文件找不到的异常。Windows文件名非法字符
你用datetime.datetime.now()的部分字符串当后缀,其中包含冒号:,而Windows文件名不允许出现该字符,会导致重命名失败或后续操作异常。
修复后的代码
import os import shutil from os import path import datetime import webbrowser import cv2 def pictures(): # 预定义路径,避免重复拼接 assets_dir = path.expandvars(r"%LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets") target_root = path.expandvars(r"%HOMEPATH%\Pictures\Desktop Backgrounds") new_bg_dir = path.join(target_root, "New Backgrounds") # 创建必要文件夹(直接判断路径是否存在更可靠) if not path.exists(target_root): os.mkdir(target_root) if not path.exists(new_bg_dir): os.mkdir(new_bg_dir) # 复制Assets中的文件到目标目录(只复制文件,排除子目录) for raw_file in os.listdir(assets_dir): src_path = path.join(assets_dir, raw_file) if path.isfile(src_path): shutil.copy(src_path, new_bg_dir) # 重命名文件为带时间戳的jpeg(替换冒号避免Windows文件名非法字符) now_suffix = str(datetime.datetime.now())[19:].replace(":", "-") file_list = os.listdir(new_bg_dir) for index, filename in enumerate(file_list): old_path = path.join(new_bg_dir, filename) # 跳过已重命名的jpeg文件,避免重复操作 if filename.lower().endswith(".jpeg"): continue new_filename = f"{index + 1}{now_suffix}.jpeg" new_path = path.join(new_bg_dir, new_filename) os.rename(old_path, new_path) # 删除小尺寸或无效图片(重命名完成后统一处理) for filename in os.listdir(new_bg_dir): file_path = path.join(new_bg_dir, filename) image = cv2.imread(file_path) if image is None: os.remove(file_path) continue # 检查宽度是否小于1920(对应常规壁纸尺寸) if image.shape[1] < 1920: os.remove(file_path) # 打开目标目录 webbrowser.open(new_bg_dir) pictures()
关键修复点
- 将模块导入移到函数外部,避免重复导入
- 用
os.path.join()规范拼接路径,消除字符串拼接的潜在错误 - 修正缩进错误,确保删除逻辑在重命名完成后执行
- 替换时间戳中的冒号,符合Windows文件名规则
- 添加文件类型判断,只复制Assets目录中的文件(排除可能的子目录)
- 跳过已重命名的jpeg文件,避免重复操作导致的异常
内容的提问来源于stack exchange,提问作者FinnFiana

