paddlenlp.utils.file_lock 源代码

# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
# Code obtained from from
# See full license at:
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import time
import errno
import functools

[文档]class FileLockException(Exception): pass
[文档]class FileLock(object): """ A file locking mechanism that has context-manager support so you can use it in a with statement. This should be relatively cross compatible as it doesn't rely on msvcrt or fcntl for the locking. """ def __init__(self, lock_file_path, timeout=-1, delay=.05): """ Prepare the file locker. Specify the file to lock and optionally the maximum timeout and the delay between each attempt to lock. """ if timeout is not None and delay is None: raise ValueError( "If timeout is not None, then delay must not be None.") self.is_locked = False self.lock_file_path = lock_file_path self.timeout = timeout self.delay = delay
[文档] def acquire(self): """ Acquire the lock, if possible. If the lock is in use, it check again every `wait` seconds. It does this until it either gets the lock or exceeds `timeout` number of seconds, in which case it throws an exception. """ start_time = time.time() while True: try: self.fd =, os.O_CREAT | os.O_EXCL | os.O_RDWR) self.is_locked = True # moved to ensure tag only when locked break except OSError as e: if e.errno != errno.EEXIST: raise if self.timeout is None: raise FileLockException( "Could not acquire lock on {}".format( self.lock_file_path)) if self.timeout > 0 and (time.time() - start_time) >= self.timeout: raise FileLockException("Timeout occured.") time.sleep(self.delay)
[文档] def release(self): """ Get rid of the lock by deleting the lockfile. When working in a `with` statement, this gets automatically called at the end. """ if self.is_locked: os.close(self.fd) os.unlink(self.lock_file_path) self.is_locked = False
def __enter__(self): """ Activated when used in the with statement. Should automatically acquire a lock to be used in the with block. """ if not self.is_locked: self.acquire() return self def __exit__(self, type, value, traceback): """ Activated at the end of the with statement. It automatically releases the lock if it isn't locked. """ if self.is_locked: self.release() def __del__(self): """ Make sure that the FileLock instance doesn't leave a lockfile lying around. """ self.release()
def decorate(lock_file_path): def _wrapper(func): @functools.wraps(func) def _impl(*args, **kwargs): with FileLock(lock_file_path): func(*args, **kwargs) return _impl return _wrapper