0
# Process Management
1
2
Core process creation, lifecycle management, and process introspection functionality. Billiard provides an enhanced Process class with additional features for worker management and timeout handling.
3
4
## Capabilities
5
6
### Process Creation and Management
7
8
Create and manage individual processes with support for daemon processes, process groups, and enhanced lifecycle control.
9
10
```python { .api }
11
class Process:
12
"""
13
Process objects represent activity running in a separate process.
14
"""
15
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, daemon=None):
16
"""
17
Create a new Process object.
18
19
Parameters:
20
- group: reserved for future extension
21
- target: callable object to invoke by run() method
22
- name: process name (string)
23
- args: argument tuple for target invocation
24
- kwargs: keyword arguments for target invocation
25
- daemon: whether process is daemon (inherits from parent if None)
26
"""
27
28
def start(self):
29
"""Start the process's activity."""
30
31
def run(self):
32
"""Method representing the process's activity (override in subclasses)."""
33
34
def join(self, timeout=None):
35
"""
36
Wait until process terminates.
37
38
Parameters:
39
- timeout: timeout in seconds (None for no timeout)
40
"""
41
42
def terminate(self):
43
"""Terminate the process using SIGTERM."""
44
45
def terminate_controlled(self):
46
"""Controlled termination with cleanup."""
47
48
def is_alive(self) -> bool:
49
"""Return whether process is alive."""
50
51
def close(self):
52
"""Close the process object and release resources."""
53
54
@property
55
def name(self) -> str:
56
"""Process name."""
57
58
@name.setter
59
def name(self, value: str):
60
"""Set process name."""
61
62
@property
63
def daemon(self) -> bool:
64
"""Daemon flag."""
65
66
@daemon.setter
67
def daemon(self, value: bool):
68
"""Set daemon flag."""
69
70
@property
71
def pid(self) -> int:
72
"""Process ID (None if not started)."""
73
74
@property
75
def ident(self) -> int:
76
"""Alias for pid."""
77
78
@property
79
def exitcode(self) -> int:
80
"""Exit code (None if not terminated)."""
81
82
@property
83
def authkey(self) -> bytes:
84
"""Authentication key."""
85
86
@authkey.setter
87
def authkey(self, value: bytes):
88
"""Set authentication key."""
89
90
@property
91
def sentinel(self) -> int:
92
"""File descriptor for waiting."""
93
```
94
95
Usage example:
96
97
```python
98
from billiard import Process
99
import time
100
import os
101
102
def worker_function(name, duration):
103
print(f"Worker {name} (PID: {os.getpid()}) starting")
104
time.sleep(duration)
105
print(f"Worker {name} finished")
106
107
# Create and start process
108
process = Process(target=worker_function, args=("Worker-1", 2))
109
process.name = "MyWorker"
110
process.daemon = False
111
process.start()
112
113
print(f"Started process {process.name} with PID {process.pid}")
114
115
# Wait for completion
116
process.join(timeout=5)
117
118
if process.is_alive():
119
print("Process is still running, terminating...")
120
process.terminate()
121
process.join()
122
123
print(f"Process exit code: {process.exitcode}")
124
process.close()
125
```
126
127
### Process Introspection
128
129
Functions to inspect the current process and active child processes.
130
131
```python { .api }
132
def current_process() -> Process:
133
"""
134
Return Process object representing the current process.
135
"""
136
137
def active_children() -> list[Process]:
138
"""
139
Return list of all alive child processes of current process.
140
Calling this has the side effect of joining any processes that have finished.
141
"""
142
143
def cpu_count() -> int:
144
"""
145
Return number of CPUs in the system.
146
147
Raises:
148
- NotImplementedError: if number of CPUs cannot be determined
149
"""
150
```
151
152
Usage example:
153
154
```python
155
from billiard import Process, current_process, active_children, cpu_count
156
157
def worker_task():
158
current = current_process()
159
print(f"Worker: {current.name} (PID: {current.pid})")
160
161
if __name__ == '__main__':
162
# Get system information
163
print(f"System has {cpu_count()} CPUs")
164
165
# Current process info
166
main_process = current_process()
167
print(f"Main process: {main_process.name} (PID: {main_process.pid})")
168
169
# Start some workers
170
processes = []
171
for i in range(3):
172
p = Process(target=worker_task, name=f"Worker-{i}")
173
p.start()
174
processes.append(p)
175
176
# Check active children
177
children = active_children()
178
print(f"Active children: {len(children)}")
179
180
# Wait for completion
181
for p in processes:
182
p.join()
183
184
# Check again
185
children = active_children()
186
print(f"Active children after join: {len(children)}")
187
```
188
189
### Authentication
190
191
Secure process authentication using authentication keys.
192
193
```python { .api }
194
class AuthenticationString(bytes):
195
"""
196
A string-like object which can be passed to multiprocessing functions
197
that accept authentication keys.
198
"""
199
def __reduce__(self):
200
"""Custom pickling to maintain security."""
201
```
202
203
Usage example:
204
205
```python
206
from billiard import Process, current_process
207
import os
208
209
def secure_worker():
210
process = current_process()
211
print(f"Worker authkey: {process.authkey[:8]}...")
212
213
if __name__ == '__main__':
214
# Set custom authentication key
215
custom_key = os.urandom(32)
216
217
process = Process(target=secure_worker)
218
process.authkey = custom_key
219
process.start()
220
process.join()
221
```
222
223
## Constants
224
225
```python { .api }
226
SUBDEBUG: int = 5
227
SUBWARNING: int = 25
228
```
229
230
These constants define additional logging levels used by billiard for detailed process debugging and warnings.