【问题标题】:portalocker does not seem to lockportalocker 似乎没有锁定
【发布时间】:2025-12-29 10:25:12
【问题描述】:

我有一种检查点文件,有时我希望通过各种 python 程序对其进行修改。我加载文件,尝试使用 portalocker 锁定它,更改它,然后解锁并关闭它。

但是,portalocker 不能在最简单的情况下工作。 我创建了一个简单的文件:

$echo "this is something here" >> test
$python
Python 3.5.2 (default, Jul  5 2016, 12:43:10) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import portalocker
>>> f = open("test",'w')
>>> portalocker.lock(f, portalocker.LOCK_EX)

同时我仍然可以在另一个终端打开它:

$python
Python 3.5.2 (default, Jul  5 2016, 12:43:10) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> fl = open("test",'w')
>>> fl.write("I can still overwrite this\n")
>>> fl.close()

然后我关闭第一个,并检查文件:

>>> portalocker.unlock(f)
>>> f.close()
>>> 
$ cat test
I can still overwrite this

我做错了什么?

【问题讨论】:

  • 无法在刚刚发布 0.6.0 的 Windows 上重复此操作 - 但它在第一个 fl.close() 上失败,而不是在 fl.write() 上。我建议你在这里打开一个问题 - github.com/WoLpH/portalocker/issues
  • 我认为您也应该在第二个终端中调用 portallocker.lock。然后这将失败,告诉您文件已被锁定。

标签: python python-3.x locking


【解决方案1】:

问题在于,默认情况下,Linux 使用咨询锁。 To enable mandatory locking (which you are referring to) the filesytem needs to be mounted with the mand option。建议锁定系统实际上有几个优点,但如果您没有预料到它可能会令人困惑。

为了确保您的代码在这两种情况下都能正常工作,我建议将两个 open 调用都用 locker 封装。

例如,在 2 个单独的 Python 实例中尝试这个:

import portalocker

with portalocker.Lock('test') as fh:
    fh.write('first instance')
    print('waiting for your input')
    input()

现在来自第二个实例:

import portalocker

with portalocker.Lock('test') as fh:
    fh.write('second instance')

Ps:我是portalocker包的维护者

【讨论】:

  • 显然我仍然没有清楚地了解这个包的功能。我把你的建议放到了一个 try/except 循环中,这似乎是第一次工作。另一方面,我无法真正摆脱锁定。我试图调用我创建的锁对象的 release() 方法,但我锁定的文件仍然是空的。
  • 该库只处理锁定,而不是读取或写入,因此如果您写入文件,它应该按预期写入。
  • 这个例子似乎过时了,截断似乎不起作用(我猜是 1.0 的变化?),超时似乎也没有任何效果。使用此示例,即使我将终端 2 中的超时设置为 10,我也会立即收到异常
  • @DavidParks:你说得对,truncate 参数已在 1.0 中删除。至于超时,它确实起作用,但仅当fail_when_locked 设置为False 时。我刚刚发布了一个改变这种行为的新版本,这样会更清晰一些。