You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

检测JSON文件是否被其他进程占用并阻止访问的代码报错排查

代码问题排查

原代码报错和逻辑失效来自两个核心问题:

  • 变量名覆盖:with open(self.name) as file 语句获取的文件对象,被后续for file in psutil.process_iter()的循环变量重名覆盖,原本可读的文件句柄被替换为psutil的Process实例,执行json.load(file)时自然找不到read方法,触发AttributeError。
  • 占用检测逻辑完全失效:原代码判断if flist就抛出异常,等价于「系统中任意进程打开了任意文件就拦截访问」,完全没有校验打开的文件是否为当前选中的JSON文件;同时psutil遍历进程的方案存在权限不足、竞态条件(检测完成到打开文件的间隙文件被其他进程抢占)的天然缺陷,根本无法实现可靠的访问拦截。
可靠实现方案

核心思路:放弃「先遍历进程检测占用、再打开文件」的非原子逻辑,直接使用操作系统级独占文件锁打开目标文件:打开动作由操作系统原子性完成,打开成功即代表当前进程拿到了文件的独占访问权,其他进程会被系统直接阻止打开;打开失败则代表文件已被占用,直接弹出提示即可。
这种方案没有竞态漏洞、不需要遍历系统进程、不受权限限制,稳定性远高于psutil遍历方案。

实现代码

import os
import json
from PyQt5 import QtWidgets

# 类内的文件打开方法
def file_open(self):
    # 选择目标JSON文件
    self.name, _filtre = QtWidgets.QFileDialog.getOpenFileName(self.centralwidget, filter='*.json')
    if not self.name: # 用户取消选择直接返回
        return

    self.file_handle = None # 全局持有文件句柄,保证锁全程生效
    try:
        # 按平台传参,以禁止其他进程读写的独占模式打开文件
        if os.name == 'nt': # Windows平台
            open_flags = os.O_RDONLY | os.O_SHARE_DENY_RW
        else: # Linux/macOS平台
            open_flags = os.O_RDONLY
        file_fd = os.open(self.name, open_flags)
        self.file_handle = os.fdopen(file_fd, 'r', encoding='utf-8')
    except PermissionError:
        # 独占打开失败 = 文件被其他进程/程序实例占用,弹框提示
        tip_dialog = QtWidgets.QDialog(self)
        tip_dialog.setWindowTitle("文件被占用")
        dialog_layout = QtWidgets.QVBoxLayout(tip_dialog)
        tip_text = QtWidgets.QLabel(f"选中的文件已被其他程序打开,请关闭对应程序后重试")
        confirm_btn = QtWidgets.QPushButton("确定")
        confirm_btn.clicked.connect(tip_dialog.accept)
        dialog_layout.addWidget(tip_text)
        dialog_layout.addWidget(confirm_btn)
        tip_dialog.exec_()
        return

    # 独占锁拿到后读取JSON内容
    try:
        self.dataTab = []
        self.jsonlist = json.load(self.file_handle)
        self.site = self.jsonlist["site"]
        self.user = self.jsonlist["user"]
        self.project = self.jsonlist["project"]
        self.dt_string = self.jsonlist["Date-Time"]
        self.dataTab = self.jsonlist['Test']
    except json.JSONDecodeError:
        QtWidgets.QMessageBox.critical(self, "文件错误", "选中的文件不是合法的JSON格式")
        self.file_handle.close()
        self.file_handle = None
        return

    # 注意:不要在这里关闭self.file_handle!
    # 需要在程序退出、用户手动关闭当前项目时再调用self.file_handle.close()释放锁
    # 锁释放前其他任何进程都无法以读写模式打开该文件

注意事项

  • 必须在程序运行期间全程持有self.file_handle,如果读取完JSON就立刻关闭句柄,文件锁会自动释放,其他实例可以正常打开文件,拦截逻辑失效。
  • 该方案是操作系统内核层面实现的访问控制,不会出现psutil方案的漏判、权限报错问题,性能也远高于遍历全系统进程的方案。

内容的提问来源于stack exchange,提问作者AlexM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 04:30:52