문제

파이썬으로 쓰기 위해 파일을 잠그어야합니다. 한 번에 여러 파이썬 프로세스에서 액세스 할 수 있습니다. 온라인에서 일부 솔루션을 찾았지만 대부분 UNIX 기반 또는 Windows 기반이므로 대부분의 목적에 실패했습니다.

도움이 되었습니까?

해결책

좋아, 그래서 나는 내가 쓴 코드로 끝났다 여기 내 웹 사이트에서 링크가 죽었고 Archive.org에서보기 (Github에서도 제공됩니다). 다음과 같은 방식으로 사용할 수 있습니다.

from filelock import FileLock

with FileLock("myfile.txt"):
    # work with the file as it is now locked
    print("Lock acquired.")

다른 팁

여기에는 크로스 플랫폼 파일 잠금 모듈이 있습니다. 포털 로커

Kevin이 말했듯이, 여러 프로세스의 파일에 한 번에 글을 쓰는 것은 가능한 경우 피하고 싶은 것입니다.

문제를 데이터베이스로 신발 할 수 있다면 sqlite를 사용할 수 있습니다. 동시 액세스를 지원하고 자체 잠금을 처리합니다.

다른 솔루션은 많은 외부 코드베이스를 인용합니다. 직접 수행하려면 Linux / DOS 시스템에서 각 파일 잠금 도구를 사용하는 크로스 플랫폼 솔루션에 대한 코드가 있습니다.

try:
    # Posix based file locking (Linux, Ubuntu, MacOS, etc.)
    import fcntl, os
    def lock_file(f):
        fcntl.lockf(f, fcntl.LOCK_EX)
    def unlock_file(f):
        fcntl.lockf(f, fcntl.LOCK_UN)
except ModuleNotFoundError:
    # Windows file locking
    import msvcrt, os
    def file_size(f):
        return os.path.getsize( os.path.realpath(f.name) )
    def lock_file(f):
        msvcrt.locking(f.fileno(), msvcrt.LK_RLCK, file_size(f))
    def unlock_file(f):
        msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, file_size(f))


# Class for ensuring that all file operations are atomic, treat
# initialization like a standard call to 'open' that happens to be atomic.
# This file opener *must* be used in a "with" block.
class AtomicOpen:
    # Open the file with arguments provided by user. Then acquire
    # a lock on that file object (WARNING: Advisory locking).
    def __init__(self, path, *args, **kwargs):
        # Open the file and acquire a lock on the file before operating
        self.file = open(path,*args, **kwargs)
        # Lock the opened file
        lock_file(self.file)

    # Return the opened file object (knowing a lock has been obtained).
    def __enter__(self, *args, **kwargs): return self.file

    # Unlock the file and close the file object.
    def __exit__(self, exc_type=None, exc_value=None, traceback=None):        
        # Flush to make sure all buffered contents are written to file.
        self.file.flush()
        os.fsync(self.file.fileno())
        # Release the lock on the file.
        unlock_file(self.file)
        self.file.close()
        # Handle exceptions that may have come up during execution, by
        # default any exceptions are raised to the user.
        if (exc_type != None): return False
        else:                  return True        

지금, AtomicOpen a에서 사용할 수 있습니다 with 일반적으로 사용하는 곳을 차단하십시오 open 성명.

경고: Windows에서 실행되고 파이썬에서 실행되는 경우 이전에 충돌합니다 출구 잠금 동작이 무엇인지 잘 모르겠습니다.

경고: 여기에 제공된 잠금은 절대적인 것이 아니라 자문입니다. 잠재적으로 경쟁하는 모든 프로세스는 "Atomicopen"클래스를 사용해야합니다.

나는 선호한다 잠금 -플랫폼 독립적 파일 잠금

잠금은 플랫폼과 장치에 따라 다르지만 일반적으로 몇 가지 옵션이 있습니다.

  1. Flock () 또는 동등한 (OS가 지원하는 경우)를 사용하십시오. 이것은 잠금 장치를 확인하지 않는 한 자문 잠금입니다.
  2. 파일을 복사하고 새 데이터를 작성한 다음 이동 (이동하지 않음 -Linux에서 원자 작업입니다-OS 확인)을 확인하면 잠금 파일의 존재.
  3. 디렉토리를 "잠금"으로 사용하십시오. NFS는 Flock ()을 지원하지 않기 때문에 NFS에 글을 쓰는 경우 필요합니다.
  4. 프로세스간에 공유 메모리를 사용할 가능성도 있지만, 나는 그것을 시도한 적이 없습니다. 매우 OS 특이 적입니다.

이러한 모든 방법에 대해서는 잠금 장치를 획득하고 테스트하기 위해 스핀 잠금 (재시험 자극) 기술을 사용해야합니다. 이것은 잘못 동기화를위한 작은 창을 남기지 만 일반적으로 큰 문제가되지 않을 정도로 작습니다.

크로스 플랫폼 인 솔루션을 찾고 있다면 다른 메커니즘을 통해 다른 시스템에 로깅하는 것이 좋습니다 (다음으로 가장 좋은 것은 위의 NFS 기술입니다).

SQLITE는 NFS에 대해 일반 파일과 동일한 제약 조건이 적용되므로 네트워크 공유에서 SQLITE 데이터베이스에 쓸 수 없으며 무료로 동기화 할 수 없습니다.

나는 그렇게 할 몇 가지 해결책을 찾고 있었고 나의 선택은oslo.concurrency

강력하고 비교적 잘 문서화되어 있습니다. 패스너를 기반으로합니다.

기타 솔루션 :

OS 수준에서 단일 파일에 대한 액세스 조정은 해결하고 싶지 않은 모든 종류의 문제로 가득 차 있습니다.

최선의 방법은 해당 파일에 대한 읽기/쓰기 액세스를 조정하는 별도의 프로세스를 갖는 것입니다.

파일 잠금은 일반적으로 플랫폼 별 작동이므로 다른 운영 체제에서 실행할 가능성이 필요할 수 있습니다. 예를 들어:

import os

def my_lock(f):
    if os.name == "posix":
        # Unix or OS X specific locking here
    elif os.name == "nt":
        # Windows specific locking here
    else:
        print "Unknown operating system, lock unavailable"

동일한 디렉토리/폴더 내에서 동일한 프로그램의 여러 사본을 실행하고 로깅 오류로 인해 이와 같은 상황을 해결하고 있습니다. 내 접근 방식은 로그 파일을 열기 전에 디스크에 "잠금 파일"을 작성하는 것이 었습니다. 프로그램은 진행하기 전에 "잠금 파일"의 존재를 확인하고 "잠금 파일"이 존재하는 경우 차례를 기다립니다.

코드는 다음과 같습니다.

def errlogger(error):

    while True:
        if not exists('errloglock'):
            lock = open('errloglock', 'w')
            if exists('errorlog'): log = open('errorlog', 'a')
            else: log = open('errorlog', 'w')
            log.write(str(datetime.utcnow())[0:-7] + ' ' + error + '\n')
            log.close()
            remove('errloglock')
            return
        else:
            check = stat('errloglock')
            if time() - check.st_ctime > 0.01: remove('errloglock')
            print('waiting my turn')

편집 --- 위의 오래된 잠금에 대한 의견 중 일부를 생각한 후 코드를 편집하여 "잠금 파일"의 튼튼한 점검을 추가했습니다. 내 시스템 에서이 함수의 수천 개의 반복시기와 평균 0.002066의 평균 ...

lock = open('errloglock', 'w')

바로 다음에 :

remove('errloglock')

그래서 나는 단지 5 배로 시작하여 문제를 나타내고 문제에 대한 상황을 모니터링 할 것이라고 생각했습니다.

또한 타이밍으로 작업 할 때 실제로 필요하지 않은 코드가 약간 있다는 것을 깨달았습니다.

lock.close()

공개 성명서에 즉시 직후에 있었기 때문에이 편집에서 제거했습니다.

그만큼 대본 그렇습니다 : 사용자는 파일을 요청합니다. 그런 다음 사용자가 동일한 요청을 다시 보내면 첫 번째 요청이 완료 될 때까지 두 번째 요청이 수행되지 않는다는 것을 사용자에게 알려줍니다. 그렇기 때문에 잠금 메커니즘을 사용 하여이 문제를 처리합니다.

내 작업 코드는 다음과 같습니다.

from lockfile import LockFile
lock = LockFile(lock_file_path)
status = ""
if not lock.is_locked():
    lock.acquire()
    status = lock.path + ' is locked.'
    print status
else:
    status = lock.path + " is already locked."
    print status

return status

나는 단순하고 일했다 (!) 구현 그리즈가 많은 파이썬에서.

간단한 사용 os.open (..., o_excl) + os.close ()가 Windows에서 작동하지 않았습니다.

당신은 찾을 수 있습니다 Pylocker 매우 유용한. 파일을 잠그거나 일반적으로 잠금 메커니즘에 사용될 수 있으며 한 번에 여러 파이썬 프로세스에서 액세스 할 수 있습니다.

단순히 파일을 잠그고 싶다면 여기에 파일이 작동하는 방법은 다음과 같습니다.

import uuid
from pylocker import Locker

#  create a unique lock pass. This can be any string.
lpass = str(uuid.uuid1())

# create locker instance.
FL = Locker(filePath='myfile.txt', lockPass=lpass, mode='w')

# aquire the lock
with FL as r:
    # get the result
    acquired, code, fd  = r

    # check if aquired.
    if fd is not None:
        print fd
        fd.write("I have succesfuly aquired the lock !")

# no need to release anything or to close the file descriptor, 
# with statement takes care of that. let's print fd and verify that.
print fd
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top