在 Python 中锁定文件
我需要锁定一个文件以便用 Python 写入。 它将同时从多个 Python 进程访问。 我在网上找到了一些解决方案,但大多数都无法达到我的目的,因为它们通常仅基于 Unix 或基于 Windows。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我需要锁定一个文件以便用 Python 写入。 它将同时从多个 Python 进程访问。 我在网上找到了一些解决方案,但大多数都无法达到我的目的,因为它们通常仅基于 Unix 或基于 Windows。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(15)
我找到了一个简单且有效的(!)实现 来自灰白蟒蛇。
简单使用 os.open(..., O_EXCL) + os.close() 在 Windows 上不起作用。
I found a simple and worked(!) implementation from grizzled-python.
Simple use os.open(..., O_EXCL) + os.close() didn't work on windows.
您可能会发现 pylocker 非常有用。 它可用于锁定文件或一般锁定机制,并且可以同时从多个 Python 进程进行访问。
如果您只是想锁定文件,其工作原理如下:
You may find pylocker very useful. It can be used to lock a file or for locking mechanisms in general and can be accessed from multiple Python processes at once.
If you simply want to lock a file here's how it works:
如果您只需要 Mac/POSIX,则无需外部软件包即可使用。
如果你想解锁文件只需更改,
If you just need Mac/POSIX this should work without external packages.
and if you want to unlock a file just change,
截至 2024 年 6 月更新
现在似乎有许多强大的、跨平台的、积极维护的解决方案。 其他答案和评论中引用最多的一些是:
原始答案
好吧,所以我最终使用了我编写的代码
这里,在我的网站上链接已失效,请在 archive.org 上查看 (也可以在 GitHub 上找到)。 我可以按以下方式使用它:Update as of June 2024
Nowadays there seem to be a number of robust, cross-platform, actively-maintained solutions to this. A few of the most cited in other answers and comments are:
Original Answer
Alright, so I ended up going with the code I wrote
here, on my websitelink is dead, view on archive.org (also available on GitHub). I can use it in the following fashion:其他解决方案引用了大量外部代码库。 如果您想自己动手,这里有一些跨平台解决方案的代码,该解决方案在 Linux / DOS 系统上使用相应的文件锁定工具。
现在,
AtomicOpen
可以在with
块中使用,其中通常使用open
语句。警告:
fcntl.lock
变得非法。The other solutions cite a lot of external code bases. If you would prefer to do it yourself, here is some code for a cross-platform solution that uses the respective file locking tools on Linux / DOS systems.
Now,
AtomicOpen
can be used in awith
block where one would normally use anopen
statement.WARNINGS:
fcntl.lock
on read-only files.这里有一个跨平台的文件锁定模块: Portalocker
虽然正如 Kevin 所说,写入文件如果可能的话,您希望避免同时来自多个进程。
如果您可以将问题硬塞到数据库中,那么您可以使用 SQLite。 它支持并发访问并处理自己的锁定。
There is a cross-platform file locking module here: Portalocker
Although as Kevin says, writing to a file from multiple processes at once is something you want to avoid if at all possible.
If you can shoehorn your problem into a database, you could use SQLite. It supports concurrent access and handles its own locking.
我一直在寻找几种解决方案来做到这一点,我的选择是
oslo.concurrency
它功能强大且文档相对完善。 它基于紧固件。
其他解决方案:
I have been looking at several solutions to do that and my choice has been
oslo.concurrency
It's powerful and relatively well documented. It's based on fasteners.
Other solutions:
我更喜欢 lockfile - 独立于平台的文件锁定
I prefer lockfile — Platform-independent file locking
锁定是特定于平台和设备的,但一般来说,您有几个选择:
对于所有这些方法,您必须使用自旋锁(失败后重试)技术来获取和测试锁。 这确实为不同步留下了一个小窗口,但它通常足够小,不会成为主要问题。
如果您正在寻找跨平台的解决方案,那么您最好通过其他机制登录到另一个系统(其次是上面的 NFS 技术)。
请注意,sqlite 与普通文件一样受到 NFS 的相同约束,因此您无法写入网络共享上的 sqlite 数据库并免费获得同步。
Locking is platform and device specific, but generally, you have a few options:
For all these methods, you'll have to use a spin-lock (retry-after-failure) technique for acquiring and testing the lock. This does leave a small window for mis-synchronization, but its generally small enough to not be a major issue.
If you're looking for a solution that is cross platform, then you're better off logging to another system via some other mechanism (the next best thing is the NFS technique above).
Note that sqlite is subject to the same constraints over NFS that normal files are, so you can't write to an sqlite database on a network share and get synchronization for free.
下面是如何使用 filelock 库的示例,该库类似于 Evan Fosmark 的实现:
with lock:
块中的任何代码都是线程安全的,这意味着它将在另一个线程之前完成访问该文件。Here's an example of how to use the filelock library, which is similar to Evan Fosmark's implementation:
Any code within the
with lock:
block is thread-safe, meaning that it will be finished before another thread has access to the file.在操作系统级别协调对单个文件的访问充满了您可能不想解决的各种问题。
最好的选择是有一个单独的进程来协调对该文件的读/写访问。
Coordinating access to a single file at the OS level is fraught with all kinds of issues that you probably don't want to solve.
Your best bet is have a separate process that coordinates read/write access to that file.
锁定文件通常是特定于平台的操作,因此您可能需要考虑在不同操作系统上运行的可能性。 例如:
Locking a file is usually a platform-specific operation, so you may need to allow for the possibility of running on different operating systems. For example:
我一直在处理这样的情况,我从同一目录/文件夹中运行同一程序的多个副本并记录错误。 我的方法是在打开日志文件之前将“锁定文件”写入光盘。 程序在继续之前检查“锁定文件”是否存在,如果“锁定文件”存在则等待轮到它。
这是代码:
编辑---
在考虑了上面关于过时锁的一些评论之后,我编辑了代码以添加对“锁定文件”的过时性的检查。 在我的系统上对这个函数进行数千次迭代的计时,从之前:
到之后:的平均时间为 0.002066... 秒,
所以我想我将从这个数量的 5 倍开始,以指示陈旧情况并监控问题情况。
另外,当我在处理时间时,我意识到我有一些并不是真正必要的代码:
我在 open 语句之后立即添加了这些代码,因此我在此编辑中删除了它。
I have been working on a situation like this where I run multiple copies of the same program from within the same directory/folder and logging errors. My approach was to write a "lock file" to the disc before opening the log file. The program checks for the presence of the "lock file" before proceeding, and waits for its turn if the "lock file" exists.
Here is the code:
EDIT---
After thinking over some of the comments about stale locks above I edited the code to add a check for staleness of the "lock file." Timing several thousand iterations of this function on my system gave and average of 0.002066... seconds from just before:
to just after:
so I figured I will start with 5 times that amount to indicate staleness and monitor the situation for problems.
Also, as I was working with the timing, I realized that I had a bit of code that was not really necessary:
which I had immediately following the open statement, so I have removed it in this edit.
这对我有用:
不要占用大文件,分成几个小文件
您创建文件 Temp,删除文件 A,然后将文件 Temp 重命名为 A。
this worked for me:
Do not occupy large files, distribute in several small ones
you create file Temp, delete file A and then rename file Temp to A.
场景是这样的:
用户请求文件来做某事。 然后,如果用户再次发送相同的请求,它会通知用户在第一个请求完成之前第二个请求尚未完成。 这就是为什么我使用锁定机制来处理这个问题。
这是我的工作代码:
The scenario is like that:
The user requests a file to do something. Then, if the user sends the same request again, it informs the user that the second request is not done until the first request finishes. That's why, I use lock-mechanism to handle this issue.
Here is my working code: