Python调用file.close()后文件仍被占用,邮件附件发送后移动文件报错求助
解决文件被占用导致
shutil.move失败的问题 核心原因
邮件发送后,附件文件的句柄未被完全释放(比如SMTP连接未关闭、文件流未关闭),导致系统仍锁定该文件,无法执行移动操作。
解决方案
1. 确保文件流被正确关闭
添加附件时,必须用with语句打开文件,保证文件自动关闭,避免手动关闭遗漏:
with open(attachment_path, "rb") as attachment_file: part = MIMEBase('application', 'octet-stream') part.set_payload(attachment_file.read()) encoders.encode_base64(part) part.add_header('Content-Disposition', f"attachment; filename={os.path.basename(attachment_path)}") msg.attach(part)
2. 显式关闭SMTP连接
发送邮件后,必须调用server.quit()或通过with语句管理SMTP连接,确保连接资源完全释放:
with smtplib.SMTP(smtp_server, smtp_port) as server: server.starttls() server.login(smtp_user, smtp_pass) server.sendmail(sender_email, receiver_email, msg.as_string()) # 显式退出,强制释放所有关联资源 server.quit()
3. 排查其他占用进程
如果以上操作仍无效,检查是否有杀毒软件、文件预览工具等第三方进程在访问目标文件,临时关闭这类工具后重试。
4. 临时延迟方案(不推荐,仅作应急)
若无法定位资源泄漏点,可在邮件发送完成后添加短暂延迟,给系统足够时间释放文件:
import time # 邮件发送完成后 time.sleep(1) shutil.move(attachment_path, archive_path)
完整示例代码
import smtplib import os import shutil import time from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders # 配置信息 smtp_server = "smtp.example.com" smtp_port = 587 smtp_user = "your_email@example.com" smtp_pass = "your_password" sender_email = "your_email@example.com" receiver_email = "target@example.com" attachment_path = "test.txt" archive_dir = "archive" archived_filename = f"test_{time.strftime('%Y%m%d_%H%M%S')}.txt" archive_path = os.path.join(archive_dir, archived_filename) # 创建归档目录(如果不存在) os.makedirs(archive_dir, exist_ok=True) # 构建邮件 msg = MIMEMultipart() msg['From'] = sender_email msg['To'] = receiver_email msg['Subject'] = "Test Email with Attachment" # 添加附件(用with保证文件关闭) with open(attachment_path, "rb") as attachment_file: part = MIMEBase('application', 'octet-stream') part.set_payload(attachment_file.read()) encoders.encode_base64(part) part.add_header('Content-Disposition', f"attachment; filename={os.path.basename(attachment_path)}") msg.attach(part) # 发送邮件并关闭连接 with smtplib.SMTP(smtp_server, smtp_port) as server: server.starttls() server.login(smtp_user, smtp_pass) server.sendmail(sender_email, receiver_email, msg.as_string()) server.quit() # 移动文件 shutil.move(attachment_path, archive_path)
内容的提问来源于stack exchange,提问作者kashif ashraf
相关产品推荐
相关产品推荐

