如何关闭脚本外打开的.csv文件?树莓派Python RFID门锁日志问题
解决CSV文件被占用导致Python脚本无法写入的问题
嘿,我来帮你搞定这个麻烦事!在Raspbian OS上,当LibreOffice打开着你的日志CSV文件时,文件会被对应的进程锁定,导致Python脚本没法写入。咱们可以通过找到并终止占用文件的进程来解决这个问题,下面是具体的实现方法:
方法一:通用型解决方案(用lsof定位所有占用进程)
lsof是Linux下专门用来查看哪些进程打开了哪些文件的工具,先确保它已经安装:
sudo apt-get install lsof
接下来可以在Python脚本里集成这段逻辑,自动关闭所有占用目标CSV的进程:
import os import subprocess import time def close_open_csv(csv_filename): """关闭所有占用指定CSV文件的进程""" try: # 调用lsof获取占用文件的进程ID列表 pid_output = subprocess.check_output( ["lsof", "-t", "-f", "--", csv_filename], stderr=subprocess.STDOUT, text=True ) pids = [pid.strip() for pid in pid_output.split('\n') if pid.strip()] if not pids: print(f"[{csv_filename}] 当前没有被其他进程占用") return # 先尝试正常终止进程(信号15),失败再强制终止(信号9) for pid in pids: try: os.kill(int(pid), 15) print(f"尝试正常终止进程 {pid}...") # 等待1秒让进程处理关闭 time.sleep(1) # 检查进程是否还在运行 os.kill(int(pid), 0) # 如果走到这里说明进程还在,强制终止 os.kill(int(pid), 9) print(f"进程 {pid} 已被强制终止") except OSError: # 进程已经关闭,跳过 print(f"进程 {pid} 已正常关闭") except subprocess.CalledProcessError as e: if e.returncode == 1: print(f"[{csv_filename}] 未找到占用进程") else: print(f"查找进程时出错:{e.output}") # 使用示例:假设你的日志文件是door_access_log.csv log_file = "door_access_log.csv" # 先关闭占用进程 close_open_csv(log_file) # 再执行写入操作 try: with open(log_file, 'a', newline='', encoding='utf-8') as f: # 这里替换成你的日志写入逻辑,比如记录时间、RFID卡号等 f.write("2024-05-20 14:30:00, RFID_12345, 进门成功\n") print("日志写入成功") except Exception as e: print(f"写入失败:{str(e)}")
方法二:针对LibreOffice的专属处理
因为你明确是LibreOffice打开了CSV,也可以直接定位LibreOffice的后台进程(一般是soffice.bin),更精准地关闭对应的实例:
import subprocess def close_libreoffice_csv(csv_filename): """关闭打开指定CSV的LibreOffice进程""" try: # 查找打开目标CSV的soffice.bin进程 lsof_result = subprocess.check_output( ["lsof", "-c", "soffice.bin", "--", csv_filename], stderr=subprocess.STDOUT, text=True ) lines = lsof_result.strip().split('\n') # 第一行是表头,从第二行开始提取PID if len(lines) > 1: pid = lines[1].split()[1] # 先尝试正常终止 subprocess.run(["kill", "-15", pid], check=True) print(f"打开[{csv_filename}]的LibreOffice进程已正常关闭") else: print(f"LibreOffice没有打开[{csv_filename}]") except subprocess.CalledProcessError as e: if e.returncode == 1: print(f"未找到打开[{csv_filename}]的LibreOffice进程") else: print(f"处理出错:{e.output}") # 使用示例 close_libreoffice_csv("door_access_log.csv")
额外小贴士
- 权限问题:如果脚本运行时提示权限不足,可以尝试用
sudo运行脚本,或者确保LibreOffice是当前用户启动的(一般都是)。 - 异常重试:可以在写入逻辑里加个重试机制,当捕获到
PermissionError时自动调用关闭函数,再重试写入,这样更健壮。 - 尽量避免强制终止:用信号15(正常终止)给LibreOffice机会保存文件,只有当正常终止失败时再用信号9(强制终止)。
内容的提问来源于stack exchange,提问作者Kevin Coleman
相关产品推荐
相关产品推荐

