Python - 如何检查文件是否被其他应用程序使用?

9
我想打开一个文件,该文件被另一个应用程序定期写入。该应用程序无法修改。因此,我只想在知道它没有被其他应用程序写入时才打开该文件。有没有Pythonic的方法来做到这一点?否则,在Unix和Windows中如何实现?
编辑:我将尝试澄清。是否有一种方法可以检查当前文件是否已被其他应用程序打开?我想从这个问题开始。现在其他应用程序的读/写是无关紧要的。我意识到这可能与操作系统有关,所以现在可能与Python无关。

1
你是想实现日志轮换吗? - vladr
不完全是,但也不算太远。我想在现有应用程序的基础上构建一个应用程序。 - Gilad Naor
3个回答

7

你的Python脚本是否需要以写入或读取方式打开文件?旧应用程序在写入之间是否打开和关闭文件,还是保持文件处于打开状态?

非常重要的是我们要了解旧应用程序正在做什么,以及您的Python脚本试图实现什么。

这个功能区高度依赖于操作系统,并且您无法控制旧应用程序只会使事情变得更加困难。是否有一种Pythonic或非Pythonic的方法来实现这一点,可能只是您最不关心的问题 - 困难的问题将是您尝试实现的内容是否可能。


更新

好的,从您的评论中知道:

旧应用程序每X分钟打开和关闭文件,但我不想假设在t = t_0 + n * X + eps时它已经关闭了文件。

那么问题的参数发生了改变。在做出一些假设的情况下,可以以一种独立于操作系统的方式完成,或者作为操作系统相关和非操作系统相关技术的组合。:)

  1. 跨平台的方法: 如果可以安全地假设遗留应用程序最多保持文件打开一段已知的时间,比如说 T 秒(例如,打开文件,执行一次写操作,然后关闭文件),并且每隔 X 秒左右重新打开它,其中 X 大于 2*T
    • stat 文件
    • now() 减去文件的修改时间,得到 D
    • 如果 T <= D < X,则打开文件并对其进行必要的操作
    • 这可能对您的应用程序足够安全。当 T/X 减小时,安全性会增加。在 *nix 上,您可能需要仔细检查 /etc/ntpd.conf 以获取正确的时间步进和慢速调整配置(请参见 tinker)。对于 Windows,请参见 MSDN
  2. Windows: 除了以上跨平台方法之外,您还可以尝试使用以下方法之一:
    • 共享(锁定):这假定遗留程序也以共享模式打开文件(通常是 Windows 应用程序的默认方式);此外,如果您的应用程序在遗留应用程序尝试执行相同操作时获得锁定(竞争条件),则遗留应用程序将失败。
      • 这种方法极其侵入性和容易出错。除非新应用程序和遗留应用程序都需要同步访问以写入同一文件,并且您愿意处理遗留应用程序无法打开文件的可能性,否则不要使用此方法。
    • 尝试找出遗留应用程序中打开的文件,使用与 ProcessExplorer 相同的技术(类似于 *nix 的 lsof
      • 您比跨平台方法更容易受到竞争条件的影响
  3. Linux/等等: 除了以上跨平台方法之外,您还可以尝试使用与 lsof 相同的技术,或者在某些系统上,仅检查符号链接 /proc/<pid>/fd/<fdes> 指向的文件是哪个
    • 您比跨平台方法更容易受到竞争条件的影响
    • 遗留应用程序很可能不使用锁定,但如果使用,除非遗留应用程序可以优雅地处理被锁定的文件(通过阻塞而不是失败 - 如果您的应用程序可以保证文件不会保持锁定状态,则会导致遗留应用程序长时间阻塞),否则锁定不是真正的选择。

更新2

如果倾向于使用“检查遗留应用程序是否打开文件”(易受竞争条件影响的侵入性方法),则可以通过以下方式解决所述竞争条件:

  1. 检查遗留应用程序是否打开文件(例如使用 lsofProcessExplorer
  2. 暂停遗留应用程序进程
  3. 重复执行步骤1以确认在步骤1和2之间遗留应用程序未打开文件。如果是,则延迟并重新开始步骤1;否则继续执行步骤4
  4. 对文件进行操作 - 理想情况下只需将其重命名以便后续独立处理,以使遗留应用程序暂停的时间尽可能短
  5. 恢复遗留应用程序进程

传统应用程序每隔X分钟打开和关闭文件,但我不想假设在t = t_0 + n*X + eps时它已经关闭了文件。 - Gilad Naor

0

Unix默认情况下没有文件锁定。我对Unix环境的最佳建议是查看lsof命令的源代码。它对哪些进程打开了哪些文件有深入的了解。您可以将其用作解决方案的基础。这里是lsof的Ubuntu源代码


这看起来可能是Unix上一个不错的解决方案。我可以在访问文件之前仅解析所需文件的lsof输出。没有锁不是完全安全,但在99.99%的情况下,我可以处理正确性。我也需要一个Windows的解决方案。 - Gilad Naor

0

我做的一件事是让Python暂时重命名文件。如果我们能够重命名它,那么就没有其他进程在使用它了。我只在Windows上测试过这个方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接