windows Python - 如何检查文件是否被另一个应用程序使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/589407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python - How to check if a file is used by another application?
提问by Gilad Naor
I want to open a file which is periodically written to by another application. This application cannot be modified. I'd therefore like to only open the file when I know it is not been written to by an other application.
我想打开一个由另一个应用程序定期写入的文件。此应用程序无法修改。因此,我只想在我知道其他应用程序未写入该文件时才打开该文件。
Is there a pythonic way to do this? Otherwise, how do I achieve this in Unix and Windows?
有没有一种pythonic的方法来做到这一点?否则,我如何在 Unix 和 Windows 中实现这一点?
edit: I'll try and clarify. Is there a way to check if the current file has been opened by another application?
编辑:我会尝试澄清。有没有办法检查当前文件是否已被另一个应用程序打开?
I'd like to start with this question. Whether those other application read/write is irrelevant for now.
我想从这个问题开始。这些其他应用程序是否读/写现在无关紧要。
I realize it is probably OS dependent, so this may not really be python related right now.
我意识到它可能依赖于操作系统,所以现在这可能不是真正与 python 相关的。
采纳答案by vladr
Will your python script desire to open the file for writing or for reading? Is the legacy application opening and closing the file between writes, or does it keep it open?
您的 Python 脚本是否希望打开文件进行写入或读取?遗留应用程序是在写入之间打开和关闭文件,还是让它保持打开状态?
It is extremely important that we understand what the legacy application is doing, and what your python script is attempting to achieve.
了解遗留应用程序在做什么以及您的 python 脚本试图实现什么是非常重要的。
This area of functionality is highly OS-dependent, and the fact that you have no control over the legacy application only makes things harder unfortunately. Whether there is a pythonic or non-pythonic way of doing this will probably be the least of your concerns - the hard question will be whether what you are trying to achieve will be possible at all.
这方面的功能高度依赖于操作系统,不幸的是,您无法控制遗留应用程序的事实只会让事情变得更加困难。是否有 Pythonic 或非 Pythonic 的方式来执行此操作可能是您最不关心的问题 - 困难的问题将是您想要实现的目标是否完全可能。
UPDATE
更新
OK, so knowing (from your comment) that:
好的,所以知道(从您的评论中):
the legacy application is opening and closing the file every X minutes, but I do not want to assume that at t = t_0 + n*X + eps it already closed the file.
旧应用程序每 X 分钟打开和关闭一次文件,但我不想假设在 t = t_0 + n*X + eps 时它已经关闭了文件。
then the problem's parameters are changed. It can actually be done in an OS-independent way given a few assumptions, or as a combination of OS-dependent and OS-independent techniques. :)
那么问题的参数就改变了。考虑到一些假设,它实际上可以以独立于操作系统的方式完成,或者作为依赖于操作系统和独立于操作系统的技术的组合。:)
- OS-independent way: if it is safe to assume that the legacy application keeps the file open for at most some known quantity of time, say
T
seconds (e.g. opens the file, performs one write, then closes the file), and re-opens it more or less everyX
seconds, whereX
is larger than 2*T
.stat
the file- subtract file's modification time from
now()
, yieldingD
- if
T
<=D
<X
then open the file and do what you need with it - This may be safe enough for your application. Safety increases as
T
/X
decreases. On *nix you may have to double check/etc/ntpd.conf
for proper time-stepping vs. slew configuration (see tinker). For Windows see MSDN
- Windows: in addition (or in-lieu) of the OS-independent method above, you may attempt to use either:
- sharing (locking): this assumes that the legacy program also opens the file in shared mode (usually the default in Windows apps); moreover, if your application acquires the lock just as the legacy application is attempting the same (race condition), the legacy application will fail.
- this is extremely intrusive and error prone. Unless both the new application and the legacy application need synchronized access for writing to the same file and you are willing to handle the possibility of the legacy application being denied opening of the file, do not use this method.
- attempting to find out what files are open in the legacy application, using the same techniques as ProcessExplorer(the equivalent of *nix's
lsof
)- you are even more vulnerable to race conditions than the OS-independent technique
- sharing (locking): this assumes that the legacy program also opens the file in shared mode (usually the default in Windows apps); moreover, if your application acquires the lock just as the legacy application is attempting the same (race condition), the legacy application will fail.
- Linux/etc.: in addition (or in-lieu) of the OS-independent method above, you may attempt to use the same technique as
lsof
or, on some systems, simply check which file the symbolic link/proc/<pid>/fd/<fdes>
points to- you are even more vulnerable to race conditions than the OS-independent technique
- it is highly unlikely that the legacy application uses locking, but if it is, locking is not a real option unless the legacy application can handle a locked file gracefully (by blocking, not by failing - and if your own application can guarantee that the file will not remain locked, blocking the legacy application for extender periods of time.)
- 独立于操作系统的方式:如果可以安全地假设遗留应用程序将文件打开最多一些已知的时间,比如
T
几秒钟(例如打开文件,执行一次写入,然后关闭文件),然后重新打开它或多或少每秒X
,其中X
大于 2*T
。stat
文件- 减去文件的修改时间
now()
,产生D
- 如果
T
<=D
<X
然后打开文件并执行您需要的操作 - 这对于您的应用程序来说可能是足够安全的。安全性随着
T
/X
减少而增加。在 *nix 上,您可能需要仔细检查/etc/ntpd.conf
正确的时间步进与回转配置(参见 tinker)。对于 Windows,请参阅MSDN
- Windows:除了(或替代)上述独立于操作系统的方法之外,您可以尝试使用:
- 共享(锁定):这假设旧程序也以共享模式打开文件(通常是 Windows 应用程序中的默认设置);此外,如果您的应用程序在旧应用程序尝试相同(竞争条件)时获取锁,则旧应用程序将失败。
- 这是非常具有侵入性且容易出错的。除非新应用程序和旧应用程序都需要同步访问以写入同一文件,并且您愿意处理旧应用程序被拒绝打开文件的可能性,否则不要使用此方法。
- 尝试使用与ProcessExplorer相同的技术(相当于 *nix's
lsof
) 找出遗留应用程序中打开了哪些文件- 与独立于操作系统的技术相比,您更容易受到竞争条件的影响
- 共享(锁定):这假设旧程序也以共享模式打开文件(通常是 Windows 应用程序中的默认设置);此外,如果您的应用程序在旧应用程序尝试相同(竞争条件)时获取锁,则旧应用程序将失败。
- Linux/等。:除了(或代替)上述独立于操作系统的方法之外,您可以尝试使用与
lsof
或在某些系统上相同的技术,只需检查符号链接/proc/<pid>/fd/<fdes>
指向 哪个文件- 与独立于操作系统的技术相比,您更容易受到竞争条件的影响
- 遗留应用程序极不可能使用锁定,但如果是,锁定就不是一个真正的选择,除非遗留应用程序可以优雅地处理锁定的文件(通过阻塞,而不是失败 - 并且如果您自己的应用程序可以保证文件不会保持锁定状态,从而在更长的时间内阻止旧应用程序。)
UPDATE 2
更新 2
If favouring the "check whether the legacy application has the file open" (intrusive approach prone to race conditions) then you can solve the said race condition by:
如果支持“检查遗留应用程序是否打开了文件”(容易出现竞争条件的侵入性方法),那么您可以通过以下方式解决所述竞争条件:
- checking whether the legacy application has the file open (a la
lsof
orProcessExplorer
) - suspending the legacy application process
- repeating the check in step 1 to confirm that the legacy application did not open the file between steps 1 and 2; delay and restart at step 1 if so, otherwise proceed to step 4
- doing your business on the file -- ideally simply renaming it for subsequent, independent processing in order to keep the legacy application suspended for a minimal amount of time
- resuming the legacy application process
- 检查遗留应用程序是否打开了文件(a la
lsof
或ProcessExplorer
) - 暂停遗留申请流程
- 重复步骤 1 中的检查以确认旧应用程序未在步骤 1 和 2 之间打开文件;如果是,则延迟并在第 1 步重新开始,否则进行第 4 步
- 在文件上开展业务——理想情况下,只需将其重命名以进行后续的独立处理,以便将遗留应用程序暂停最少的时间
- 恢复原有的申请流程
回答by Peter Rowell
Unix does not have file locking as a default. The best suggestion I have for a Unix environment would be to look at the sources for the lsof command. It has deep knowledge about which process have which files open. You could use that as the basis of your solution. Here are the Ubuntu sources for lsof.
Unix 默认没有文件锁定。我对 Unix 环境的最佳建议是查看 lsof 命令的源代码。它对哪个进程打开了哪些文件有深入的了解。您可以将其用作解决方案的基础。这是lsof的Ubuntu 源。
回答by Jim Carroll
One thing I've done is have python very temporarily rename the file. If we're able to rename it, then no other process is using it. I only tested this on Windows.
我做过的一件事是让 python 临时重命名文件。如果我们能够重命名它,那么就没有其他进程在使用它。我只在 Windows 上测试过这个。