0
# File Locking
1
2
Core file locking functionality using advisory locks with support for exclusive/shared locks, non-blocking mode, and timeout handling. Works across Windows, Linux, Unix, and macOS with automatic platform-specific implementation selection.
3
4
## Capabilities
5
6
### Basic Locking Functions
7
8
Low-level file locking functions that provide direct control over file locks using native system calls.
9
10
```python { .api }
11
def lock(file: FileArgument, flags: LockFlags) -> None:
12
"""
13
Lock a file using advisory locking.
14
15
Parameters:
16
- file: File object, file descriptor, or object with fileno() method
17
- flags: Locking flags (LOCK_EX, LOCK_SH, LOCK_NB combinations)
18
19
Raises:
20
- LockException: If locking fails due to system error
21
- AlreadyLocked: If file is already locked and LOCK_NB is specified
22
"""
23
24
def unlock(file: FileArgument) -> None:
25
"""
26
Unlock a previously locked file.
27
28
Parameters:
29
- file: File object, file descriptor, or object with fileno() method
30
31
Raises:
32
- LockException: If unlocking fails due to system error
33
"""
34
```
35
36
### Lock Constants
37
38
Flag constants for controlling lock behavior, automatically set to appropriate values for the current platform.
39
40
```python { .api }
41
LOCK_EX: LockFlags # Exclusive lock - only one process can hold this lock
42
LOCK_SH: LockFlags # Shared lock - multiple processes can hold shared locks simultaneously
43
LOCK_NB: LockFlags # Non-blocking - fail immediately if lock cannot be acquired
44
LOCK_UN: LockFlags # Unlock - remove existing lock (used internally)
45
46
# Enum version with the same values
47
class LockFlags(enum.IntFlag):
48
EXCLUSIVE: int # Same as LOCK_EX
49
SHARED: int # Same as LOCK_SH
50
NON_BLOCKING: int # Same as LOCK_NB
51
UNBLOCK: int # Same as LOCK_UN
52
```
53
54
### Usage Examples
55
56
Basic file locking with manual lock/unlock:
57
58
```python
59
import portalocker
60
61
# Exclusive lock (default)
62
with open('data.txt', 'r+') as fh:
63
portalocker.lock(fh, portalocker.LOCK_EX)
64
try:
65
# File is now exclusively locked
66
data = fh.read()
67
fh.seek(0)
68
fh.write('modified: ' + data)
69
fh.truncate()
70
finally:
71
portalocker.unlock(fh)
72
```
73
74
Non-blocking lock with error handling:
75
76
```python
77
import portalocker
78
79
try:
80
with open('data.txt', 'r+') as fh:
81
# Try to lock immediately, fail if already locked
82
portalocker.lock(fh, portalocker.LOCK_EX | portalocker.LOCK_NB)
83
# Work with file
84
data = fh.read()
85
portalocker.unlock(fh)
86
except portalocker.AlreadyLocked:
87
print("File is currently locked by another process")
88
except portalocker.LockException as e:
89
print(f"Locking failed: {e}")
90
```
91
92
Shared locks for read-only access:
93
94
```python
95
import portalocker
96
97
# Multiple processes can hold shared locks simultaneously
98
with open('config.txt', 'r') as fh:
99
portalocker.lock(fh, portalocker.LOCK_SH)
100
try:
101
config_data = fh.read()
102
# Process read-only data
103
finally:
104
portalocker.unlock(fh)
105
```
106
107
Working with file descriptors:
108
109
```python
110
import os
111
import portalocker
112
113
# Lock using file descriptor
114
fd = os.open('data.txt', os.O_RDWR)
115
try:
116
portalocker.lock(fd, portalocker.LOCK_EX)
117
# Work with file descriptor
118
data = os.read(fd, 1024)
119
os.write(fd, b'new data')
120
portalocker.unlock(fd)
121
finally:
122
os.close(fd)
123
```
124
125
## Platform-Specific Behavior
126
127
### Windows Implementation
128
- Uses Win32 API (LockFileEx/UnlockFileEx) or msvcrt.locking
129
- Supports both exclusive and shared locks
130
- File position is preserved during locking operations
131
- Automatic fallback between implementation methods
132
133
### POSIX Implementation
134
- Uses fcntl.flock for advisory locking
135
- Supports exclusive, shared, and non-blocking modes
136
- Works with file descriptors and file objects
137
- Compatible with Linux, Unix, macOS, and other POSIX systems
138
139
### Error Handling
140
141
Common error scenarios and their exceptions:
142
143
```python
144
# File already locked by another process
145
try:
146
portalocker.lock(fh, portalocker.LOCK_EX | portalocker.LOCK_NB)
147
except portalocker.AlreadyLocked as e:
148
print(f"File locked by: {e.fh}")
149
150
# System-level locking error
151
try:
152
portalocker.lock(fh, portalocker.LOCK_EX)
153
except portalocker.LockException as e:
154
print(f"Locking failed: {e.strerror}")
155
```
156
157
## Type Definitions
158
159
```python { .api }
160
from typing import Union, Protocol
161
import typing
162
import io
163
164
# File argument types accepted by lock/unlock functions
165
FileArgument = Union[typing.IO[typing.Any], io.TextIOWrapper, int, HasFileno]
166
167
class HasFileno(Protocol):
168
"""Protocol for objects that have a fileno() method"""
169
def fileno(self) -> int: ...
170
171
# Lock flags enum
172
class LockFlags(enum.IntFlag):
173
EXCLUSIVE: int # Exclusive lock
174
SHARED: int # Shared lock
175
NON_BLOCKING: int # Non-blocking mode
176
UNBLOCK: int # Unlock operation
177
```