0
# Lock Classes
1
2
High-level lock managers with built-in timeout, context manager support, and advanced features like reentrant locks and temporary file locks. These classes provide a more convenient interface than the low-level lock/unlock functions.
3
4
## Capabilities
5
6
### Lock Class
7
8
The primary high-level lock manager with automatic file handling, timeout support, and context manager interface.
9
10
```python { .api }
11
class Lock:
12
"""
13
Lock manager with built-in timeout and context manager support.
14
15
Parameters:
16
- filename: Path to file to lock (str or pathlib.Path)
17
- mode: File open mode ('a', 'r+', 'w+', etc.). 'w' modes truncate after lock acquisition
18
- timeout: Timeout in seconds when trying to acquire lock (default: 5.0)
19
- check_interval: Check interval while waiting for lock (default: 0.25)
20
- fail_when_locked: Fail immediately if initial lock fails (default: False)
21
- flags: Lock flags (default: LOCK_EX | LOCK_NB)
22
- **file_open_kwargs: Additional arguments passed to open()
23
"""
24
25
def __init__(self, filename: Filename, mode: str = 'a', timeout: float | None = None,
26
check_interval: float = 0.25, fail_when_locked: bool = False,
27
flags: LockFlags = LOCK_EX | LOCK_NB, **file_open_kwargs) -> None: ...
28
29
def acquire(self, timeout: float | None = None, check_interval: float | None = None,
30
fail_when_locked: bool | None = None) -> typing.IO:
31
"""
32
Acquire the file lock and return file handle.
33
34
Parameters:
35
- timeout: Override default timeout
36
- check_interval: Override default check interval
37
- fail_when_locked: Override default fail_when_locked behavior
38
39
Returns:
40
- File handle for the locked file
41
42
Raises:
43
- AlreadyLocked: If lock cannot be acquired and fail_when_locked=True
44
- LockException: If locking fails due to system error
45
"""
46
47
def release(self) -> None:
48
"""Release the currently held lock and close file handle"""
49
50
def __enter__(self) -> typing.IO:
51
"""Context manager entry - acquire lock and return file handle"""
52
53
def __exit__(self, exc_type, exc_value, traceback) -> None:
54
"""Context manager exit - release lock"""
55
```
56
57
### Reentrant Lock (RLock)
58
59
A reentrant lock that can be acquired multiple times by the same process, similar to threading.RLock.
60
61
```python { .api }
62
class RLock(Lock):
63
"""
64
Reentrant lock that can be acquired multiple times by the same process.
65
Must be released the same number of times it was acquired.
66
"""
67
68
def __init__(self, filename: Filename, mode: str = 'a', timeout: float = 5.0,
69
check_interval: float = 0.25, fail_when_locked: bool = False,
70
flags: LockFlags = LOCK_EX | LOCK_NB) -> None: ...
71
72
def acquire(self, timeout: float | None = None, check_interval: float | None = None,
73
fail_when_locked: bool | None = None) -> typing.IO:
74
"""Acquire lock (can be called multiple times by same process)"""
75
76
def release(self) -> None:
77
"""Release lock (must match number of acquire() calls)"""
78
```
79
80
### Temporary File Lock
81
82
A lock that uses a temporary file and automatically cleans up the lock file when released.
83
84
```python { .api }
85
class TemporaryFileLock(Lock):
86
"""
87
Temporary file lock that auto-deletes the lock file on release.
88
Automatically registers cleanup with atexit.
89
"""
90
91
def __init__(self, filename: str = '.lock', timeout: float = 5.0,
92
check_interval: float = 0.25, fail_when_locked: bool = True,
93
flags: LockFlags = LOCK_EX | LOCK_NB) -> None: ...
94
95
def release(self) -> None:
96
"""Release lock and delete the temporary lock file"""
97
```
98
99
### Usage Examples
100
101
Basic usage with context manager:
102
103
```python
104
import portalocker
105
106
# Simple file locking with automatic cleanup
107
with portalocker.Lock('data.txt', 'r+', timeout=10.0) as fh:
108
# File is automatically locked here
109
data = fh.read()
110
fh.seek(0)
111
fh.write('modified: ' + data)
112
fh.truncate()
113
# File is automatically unlocked and closed here
114
```
115
116
Manual lock management:
117
118
```python
119
import portalocker
120
121
# Create lock object
122
lock = portalocker.Lock('data.txt', mode='r+', timeout=5.0)
123
124
try:
125
# Acquire lock
126
fh = lock.acquire()
127
128
# Work with file
129
data = fh.read()
130
fh.write('new data')
131
132
finally:
133
# Always release lock
134
lock.release()
135
```
136
137
Reentrant locking:
138
139
```python
140
import portalocker
141
142
def process_file_nested():
143
with portalocker.RLock('data.txt', 'r+') as fh1:
144
# First lock acquisition
145
data = fh1.read()
146
147
# Nested function that also needs the same lock
148
with portalocker.RLock('data.txt', 'r+') as fh2:
149
# Second lock acquisition by same process - succeeds
150
fh2.write('nested access: ' + data)
151
152
# First lock still held here
153
fh1.write('outer access completed')
154
# All locks released here
155
```
156
157
Temporary lock files:
158
159
```python
160
import portalocker
161
162
# Create a temporary lock for process coordination
163
with portalocker.TemporaryFileLock('/tmp/my_process.lock') as fh:
164
# Only one instance of this process can run
165
print("Starting exclusive process...")
166
do_exclusive_work()
167
print("Process completed")
168
# Lock file is automatically deleted
169
```
170
171
Non-blocking behavior:
172
173
```python
174
import portalocker
175
176
try:
177
# Fail immediately if file is already locked
178
with portalocker.Lock('data.txt', fail_when_locked=True, timeout=0) as fh:
179
process_file(fh)
180
except portalocker.AlreadyLocked:
181
print("File is currently being processed by another instance")
182
```
183
184
Custom file open parameters:
185
186
```python
187
import portalocker
188
189
# Pass additional parameters to open()
190
with portalocker.Lock('data.txt', 'r+', encoding='utf-8', buffering=1) as fh:
191
# File opened with custom encoding and line buffering
192
text_data = fh.read()
193
fh.write('unicode data: ' + text_data)
194
```
195
196
Timeout and retry behavior:
197
198
```python
199
import portalocker
200
import time
201
202
# Custom timeout and check intervals
203
lock = portalocker.Lock(
204
'data.txt',
205
timeout=30.0, # Wait up to 30 seconds
206
check_interval=0.5, # Check every 500ms
207
fail_when_locked=False # Keep retrying until timeout
208
)
209
210
try:
211
with lock:
212
# Will retry acquiring lock for up to 30 seconds
213
process_file()
214
except portalocker.LockException:
215
print("Could not acquire lock within 30 seconds")
216
```
217
218
## Error Handling
219
220
Lock classes raise the same exceptions as the low-level functions:
221
222
```python
223
try:
224
with portalocker.Lock('data.txt', fail_when_locked=True) as fh:
225
process_file(fh)
226
except portalocker.AlreadyLocked as e:
227
print(f"File is locked: {e}")
228
except portalocker.LockException as e:
229
print(f"Lock failed: {e}")
230
except FileNotFoundError:
231
print("File does not exist")
232
```
233
234
## Type Definitions
235
236
```python { .api }
237
from typing import Union
238
import pathlib
239
import typing
240
241
Filename = Union[str, pathlib.Path]
242
243
class LockFlags(enum.IntFlag):
244
EXCLUSIVE: int
245
SHARED: int
246
NON_BLOCKING: int
247
UNBLOCK: int
248
249
# Default lock method used by Lock classes
250
LOCK_METHOD = LockFlags.EXCLUSIVE | LockFlags.NON_BLOCKING
251
```