首页 > 解决方案 > Portalocker 未按预期退出,而 fcntl 则退出

问题描述

我不明白为什么 portallocker 没有优雅地失败并显示“有一个锁文件”的消息。相反,它失败并出现以下错误:

portalocker.exceptions.LockException: [Errno 11] Resource temporarily unavailable

请注意,该问题已被提出,但没有人令人信服地回答。请参阅python-lock-a-file 这是有问题的脚本,它必须在两个不同的控制台中启动。

#!/usr/bin/python3

import portalocker
import sys

def open_and_lock(full_filename):
    file_handle = open(full_filename, 'w')
    try:
        portalocker.lock(file_handle, portalocker.LOCK_EX | portalocker.LOCK_NB)
        return file_handle
    except IOError:
        print ("there is a lockfile")
        sys.exit(-1)

# positioning a lock
lock_name = 'my_lock'
fh = open_and_lock(lock_name)

# do something consumer in time
i = 0
while (i < 100000000):
    i += 1
    print ("i :", i)

# lock release
close(fh)

用 fcntl 替换 portalocker 并且......一切正常!

#!/usr/bin/python3

import fcntl
import sys

def open_and_lock(full_filename):
    file_handle = open(full_filename, 'w')
    try:
        fcntl.lockf(file_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
        return file_handle
    except IOError:
        print ("there is a lockfile")
        sys.exit(-1)

# positioning a lock
lock_name = 'my_lock'
fh = open_and_lock(lock_name)

# do something consumer in time
i = 0
while (i < 100000000):
    i += 1
    print ("i :", i)

# lock release
close(fh)

到底是怎么回事 ?为什么portalocker和fcntl之间的这种行为差异?

ps:Python 3.6.7 Ubuntu 18.04

标签: pythonpython-3.xlockingtry-catchfcntl

解决方案


例外一个优雅的例外:portalocker.exceptions.LockException

与直接使用相反fcntlportalocker它包装了异常,因此它可以在多个平台上运行。该fcntl示例在 Windows 上不起作用,portalocker确实:)

测试显示了一些有用的示例:https ://github.com/WoLpH/portallocker/blob/develop/portallocker_tests/tests.py

在您的情况下,IOError您应该捕获而不是捕获portalocker.exceptions.LockException. 此外,您还应该始终正确解锁,因此我建议改为:

#!/usr/bin/python3

import portalocker
import sys


# positioning a lock
lock_name = 'my_lock'

try:
    with portalocker.Lock(lock_name, portalocker.LOCK_EX | portalocker.LOCK_NB):
        # do something consumer in time
        i = 0
        while (i < 100000000):
            i += 1
            print ("i :", i)
except portalocker.exceptions.LockException:
    print ("there is a lockfile")
    sys.exit(-1)

或者,如果您真的想显式锁定和解锁:

#!/usr/bin/python3

import portalocker
import sys

def open_and_lock(full_filename):
    file_handle = open(full_filename, 'w')
    try:
        portalocker.lock(file_handle, portalocker.LOCK_EX | portalocker.LOCK_NB)
        return file_handle
    except portalocker.exceptions.LockException:
        print ("there is a lockfile")
        sys.exit(-1)

# positioning a lock
lock_name = 'my_lock'
fh = open_and_lock(lock_name)

try:
    # do something consumer in time
    i = 0
    while (i < 100000000):
        i += 1
        print ("i :", i)
finally:
    # lock release
    portalocker.unlock(fh)

推荐阅读