使用Python Watchdog库报错:'nt.DirEntry'对象无'rstrip'属性
音频文件自动移动脚本 AttributeError 问题解决
参考YouTube教程写了个音频文件自动移动脚本,用scandir和watchdog实现功能,但运行时一直报AttributeError,提示'nt.DirEntry'对象不存在'rstrip'属性,自己调整代码后还是解决不了,求帮忙。脚本代码如下:
from os import scandir, rename from os.path import splitext, exists, join from shutil import move import time import logging from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler source_dir=r'*censored*' mp3_dir=r'*censored*' # ? supported Audio types audio_extensions = [".m4a", ".flac", "mp3", ".wav", ".wma", ".aac"] def make_unique(dest, name): filename, extension = splitext(name) counter = 1 # * IF FILE EXISTS, ADDS NUMBER TO THE END OF THE FILENAME while exists(f"{dest}/{name}"): name = f"{filename}({str(counter)}){extension}" counter += 1 return name def move_file(dest, entry, name): if exists(f"{dest}/{name}"): unique_name = make_unique(dest, name) oldName = join(dest, name) newName = join(dest, unique_name) rename(oldName, newName) move(entry, dest) class MoverHandler(FileSystemEventHandler): # ? THIS FUNCTION WILL RUN WHENEVER THERE IS A CHANGE IN "source_dir" # ? .upper is for not missing out on files with uppercase extensions def on_modified(self, event): with scandir(source_dir) as entries: for entry in entries: name = entry.name self.check_audio_files(entry, name) def check_audio_files(self, entry, name): # * Checks all Audio Files for audio_extension in audio_extensions: if name.endswith(audio_extension) or name.endswith(audio_extension.upper()): dest = mp3_dir move_file(dest, entry, name) logging.info(f"Moved audio file: {name}") if __name__ == "__main__": logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S') path = source_dir event_handler = MoverHandler() observer = Observer() observer.schedule(event_handler, path, recursive=True) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()
问题原因
核心问题出在move_file函数里的move(entry, dest)这一行:shutil.move()要求第一个参数是文件路径的字符串,但你传的是scandir返回的DirEntry对象。shutil.move内部会对路径做字符串处理(比如调用rstrip),而DirEntry是个对象,没有这些字符串方法,所以触发了错误。
另外原代码存在缩进问题(Python对缩进严格),部分代码块缩进不正确,也会导致运行异常。
修复后的完整代码
from os import scandir, rename from os.path import splitext, exists, join from shutil import move import time import logging from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler source_dir=r'*censored*' mp3_dir=r'*censored*' # 支持的音频格式 audio_extensions = [".m4a", ".flac", ".mp3", ".wav", ".wma", ".aac"] def make_unique(dest, name): filename, extension = splitext(name) counter = 1 # 如果文件已存在,给文件名加数字后缀 while exists(f"{dest}/{name}"): name = f"{filename}({str(counter)}){extension}" counter += 1 return name def move_file(dest, entry, name): if exists(f"{dest}/{name}"): unique_name = make_unique(dest, name) oldName = join(dest, name) newName = join(dest, unique_name) rename(oldName, newName) # 核心修复:传入文件路径字符串而非DirEntry对象,同时指定完整目标路径 move(entry.path, join(dest, name)) class MoverHandler(FileSystemEventHandler): # 当source_dir有变化时触发 # .upper是为了不遗漏大写扩展名的文件 def on_modified(self, event): with scandir(source_dir) as entries: for entry in entries: # 跳过目录,只处理文件 if entry.is_file(): name = entry.name self.check_audio_files(entry, name) def check_audio_files(self, entry, name): # 检查所有音频文件 for audio_extension in audio_extensions: if name.endswith(audio_extension) or name.endswith(audio_extension.upper()): dest = mp3_dir move_file(dest, entry, name) logging.info(f"Moved audio file: {name}") if __name__ == "__main__": logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S') path = source_dir event_handler = MoverHandler() observer = Observer() observer.schedule(event_handler, path, recursive=True) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()
关键修改点
- 核心错误修复:将
move(entry, dest)改为move(entry.path, join(dest, name)),entry.path是文件的完整路径字符串,符合shutil.move的参数要求;同时指定目标路径的完整文件名,避免移动后文件名异常。 - 缩进修正:修复了
make_unique、move_file函数内部的缩进问题,确保Python能正确识别代码块。 - 添加目录过滤:在
on_modified里增加if entry.is_file()判断,避免尝试移动目录导致的额外错误。 - 扩展名修正:把原列表里的
"mp3"改成".mp3",保证扩展名匹配逻辑正确。
内容的提问来源于stack exchange,提问作者ayevee
相关产品推荐
相关产品推荐

