0
# Portalocker
1
2
A cross-platform file locking library that provides reliable file locking mechanisms across Windows, Linux, Unix, and macOS systems. Portalocker offers both traditional file-based locks using native system calls and advanced Redis-based distributed locks for multi-process and multi-machine coordination.
3
4
## Package Information
5
6
- **Package Name**: portalocker
7
- **Language**: Python
8
- **Installation**: `pip install portalocker`
9
- **Optional Dependencies**: `pip install portalocker[redis]` for Redis-based locking
10
11
## Core Imports
12
13
```python
14
import portalocker
15
```
16
17
Common usage patterns:
18
19
```python
20
from portalocker import Lock, lock, unlock, LOCK_EX, LOCK_SH, LOCK_NB
21
```
22
23
For Redis-based locking:
24
25
```python
26
from portalocker import RedisLock
27
```
28
29
## Basic Usage
30
31
```python
32
import portalocker
33
34
# Basic file locking with context manager
35
with portalocker.Lock('my_file.txt', 'r+') as fh:
36
data = fh.read()
37
# File is automatically locked here
38
fh.write('new data')
39
# File is automatically unlocked when exiting context
40
41
# Manual locking and unlocking
42
with open('my_file.txt', 'r+') as fh:
43
portalocker.lock(fh, portalocker.LOCK_EX)
44
try:
45
# Do work with locked file
46
data = fh.read()
47
fh.write('modified data')
48
finally:
49
portalocker.unlock(fh)
50
51
# Non-blocking lock with timeout
52
try:
53
with portalocker.Lock('my_file.txt', timeout=5.0, fail_when_locked=True) as fh:
54
# Work with file
55
pass
56
except portalocker.AlreadyLocked:
57
print("File is locked by another process")
58
```
59
60
## Architecture
61
62
Portalocker provides a layered architecture for cross-platform file locking:
63
64
- **High-level Lock Classes**: Context managers (Lock, RLock, TemporaryFileLock) with timeout and error handling
65
- **Low-level Functions**: Direct lock/unlock functions (lock, unlock) for manual control
66
- **Platform Abstraction**: Automatic selection between Windows (Win32/msvcrt) and POSIX (fcntl) implementations
67
- **Advanced Features**: Redis-based distributed locks, bounded semaphores, atomic file operations
68
- **Type System**: Complete type definitions for all file handles, flags, and configuration options
69
70
This design ensures reliable cross-platform operation while providing flexibility from simple context managers to complex distributed locking scenarios.
71
72
## Capabilities
73
74
### File Locking
75
76
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.
77
78
```python { .api }
79
def lock(file: FileArgument, flags: LockFlags) -> None: ...
80
def unlock(file: FileArgument) -> None: ...
81
82
LOCK_EX: LockFlags # Exclusive lock
83
LOCK_SH: LockFlags # Shared lock
84
LOCK_NB: LockFlags # Non-blocking
85
LOCK_UN: LockFlags # Unlock
86
```
87
88
[File Locking](./file-locking.md)
89
90
### Lock Classes
91
92
High-level lock managers with built-in timeout, context manager support, and advanced features like reentrant locks and temporary file locks.
93
94
```python { .api }
95
class Lock:
96
def __init__(self, filename: Filename, mode: str = 'a', timeout: float | None = None,
97
check_interval: float = 0.25, fail_when_locked: bool = False,
98
flags: LockFlags = LOCK_EX | LOCK_NB, **file_open_kwargs) -> None: ...
99
def acquire(self, timeout: float | None = None, check_interval: float | None = None,
100
fail_when_locked: bool | None = None) -> typing.IO: ...
101
def release(self) -> None: ...
102
103
class RLock(Lock): ... # Reentrant lock
104
class TemporaryFileLock(Lock): ... # Auto-deleting temporary lock
105
```
106
107
[Lock Classes](./lock-classes.md)
108
109
### Redis Distributed Locking
110
111
Redis pubsub-based distributed locks that provide immediate unlocking when connections are lost, suitable for multi-process and multi-machine coordination.
112
113
```python { .api }
114
class RedisLock:
115
def __init__(self, channel: str, connection: redis.Redis | None = None,
116
timeout: float | None = None, check_interval: float | None = None,
117
fail_when_locked: bool | None = False, thread_sleep_time: float = 0.1,
118
unavailable_timeout: float = 1, redis_kwargs: dict | None = None) -> None: ...
119
def acquire(self, timeout: float | None = None, check_interval: float | None = None,
120
fail_when_locked: bool | None = None) -> 'RedisLock': ...
121
def release(self) -> None: ...
122
```
123
124
[Redis Locking](./redis-locking.md)
125
126
### Semaphores and Resource Management
127
128
Bounded semaphores for limiting concurrent processes accessing shared resources, with support for named semaphores across process boundaries.
129
130
```python { .api }
131
class BoundedSemaphore: # Deprecated
132
def __init__(self, maximum: int, name: str = 'bounded_semaphore',
133
filename_pattern: str = '{name}.{number:02d}.lock',
134
directory: str = tempfile.gettempdir(), **kwargs) -> None: ...
135
136
class NamedBoundedSemaphore(BoundedSemaphore):
137
def __init__(self, maximum: int, name: str | None = None, **kwargs) -> None: ...
138
```
139
140
[Semaphores](./semaphores.md)
141
142
### Utility Functions
143
144
Additional utilities for atomic file operations and helper functions.
145
146
```python { .api }
147
def open_atomic(filename: Filename, binary: bool = True) -> typing.Iterator[typing.IO]: ...
148
```
149
150
[Utilities](./utilities.md)
151
152
## Exception Handling
153
154
```python { .api }
155
class LockException(Exception):
156
"""Base exception for locking errors"""
157
158
class AlreadyLocked(LockException):
159
"""Raised when file is already locked by another process"""
160
```
161
162
## Type Definitions
163
164
```python { .api }
165
from typing import Union, Literal
166
import pathlib
167
168
# File path types
169
Filename = Union[str, pathlib.Path]
170
171
# File handle types
172
FileArgument = Union[typing.IO, int, HasFileno]
173
174
# File open modes
175
Mode = Literal['r', 'w', 'a', 'x', 'rb', 'wb', 'ab', 'xb', 'r+', 'w+', 'a+', 'x+', ...]
176
177
# Lock flags enum
178
class LockFlags(enum.IntFlag):
179
EXCLUSIVE: int
180
SHARED: int
181
NON_BLOCKING: int
182
UNBLOCK: int
183
184
# Protocol for objects with fileno() method
185
class HasFileno(typing.Protocol):
186
def fileno(self) -> int: ...
187
```