GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing zetcode.com — Python os.wait4 Function - Complete Guide Python os.wait4 FunctionLast modified April 11, 2025
This comprehensive guide explores Python's Basic Definitions
The Key parameters: pid (process ID to wait for), options (flags like WNOHANG). Returns a tuple of (pid, status, resource_usage). Unix systems only. Basic Process Waiting
The simplest use of basic_wait.py
import os
import time
pid = os.fork()
if pid == 0: # Child process
print("Child process running")
time.sleep(2)
print("Child process exiting")
os._exit(0)
else: # Parent process
print(f"Parent waiting for child {pid}")
pid, status, rusage = os.wait4(pid, 0)
print(f"Child {pid} exited with status {status}")
print(f"Resource usage: {rusage}")
This creates a child process that sleeps for 2 seconds. The parent waits for it to complete using os.wait4. The resource usage information includes CPU time and memory usage. The status contains the exit code and signal information if the process was terminated by a signal. Non-blocking Wait with WNOHANGThe WNOHANG option makes os.wait4 non-blocking. It returns immediately if no child process has terminated. This allows polling while doing other work. non_blocking.py
import os
import time
pid = os.fork()
if pid == 0: # Child
time.sleep(3)
os._exit(42)
else: # Parent
print("Parent checking child status...")
while True:
result = os.wait4(pid, os.WNOHANG)
if result[0] == 0:
print("Child still running...")
time.sleep(1)
else:
pid, status, rusage = result
print(f"Child exited with status {status >> 8}")
break
The parent periodically checks the child's status without blocking. When WNOHANG is used and the child hasn't exited, wait4 returns (0, 0, 0). The exit status is encoded in the status value. Right-shifting by 8 bits extracts the actual exit code (42 in this case). Waiting for Specific ProcessYou can wait for a specific child process by providing its PID. This is useful when managing multiple child processes independently. specific_process.py
import os
import time
children = []
for i in range(3):
pid = os.fork()
if pid == 0: # Child
time.sleep(i + 1)
os._exit(i)
else:
children.append(pid)
print(f"Started child {pid}")
# Wait for middle child (second in list)
target_pid = children[1]
pid, status, rusage = os.wait4(target_pid, 0)
print(f"Child {pid} exited with status {status >> 8}")
# Wait for remaining children
for pid in children:
if pid != target_pid:
os.wait4(pid, 0)
This creates three child processes with different sleep durations. The parent first waits specifically for the second child (PID in children[1]). After handling the specific child, it waits for the remaining children to prevent zombie processes. Handling Resource Usage InformationThe resource usage information provides detailed statistics about the child's execution. This example demonstrates interpreting these values. resource_usage.py
import os
import time
import resource
pid = os.fork()
if pid == 0: # Child
# Use some CPU and memory
start = time.time()
while time.time() - start < 1: # Burn CPU for 1 second
pass
data = "x" * 10_000_000 # Allocate memory
time.sleep(0.5)
os._exit(0)
else: # Parent
pid, status, rusage = os.wait4(pid, 0)
print("Resource usage statistics:")
print(f"User CPU time: {rusage.ru_utime:.3f} seconds")
print(f"System CPU time: {rusage.ru_stime:.3f} seconds")
print(f"Max RSS: {rusage.ru_maxrss} KB")
print(f"Page faults: {rusage.ru_majflt} major, {rusage.ru_minflt} minor")
The child process performs CPU-intensive work and allocates memory. The parent prints detailed resource usage statistics after the child exits. Key metrics include CPU time (user and system), maximum resident set size (memory), and page fault counts. Handling Terminated ChildrenWhen a child process terminates abnormally (e.g., by signal), os.wait4 provides information about the termination cause in the status value. signal_handling.py
import os
import signal
import time
pid = os.fork()
if pid == 0: # Child
print("Child running")
time.sleep(5)
print("Child exiting normally")
os._exit(0)
else: # Parent
time.sleep(1)
os.kill(pid, signal.SIGTERM)
pid, status, rusage = os.wait4(pid, 0)
if os.WIFEXITED(status):
print(f"Child exited normally with status {os.WEXITSTATUS(status)}")
elif os.WIFSIGNALED(status):
print(f"Child terminated by signal {os.WTERMSIG(status)}")
elif os.WIFSTOPPED(status):
print(f"Child stopped by signal {os.WSTOPSIG(status)}")
The parent sends SIGTERM to the child after 1 second. The wait4 call then returns information about this signal termination. The WIF... functions help interpret the status value to determine how the process terminated (normally, by signal, or stopped). Waiting for Any Child ProcessUsing pid=-1 with os.wait4 waits for any child process to terminate. This is useful when managing multiple children without tracking specific PIDs. any_child.py
import os
import time
import random
# Start several child processes
children = []
for i in range(5):
pid = os.fork()
if pid == 0: # Child
sleep_time = random.randint(1, 5)
time.sleep(sleep_time)
os._exit(sleep_time)
else:
children.append(pid)
print(f"Started child {pid} (will sleep {i+1}s)")
# Wait for any child to finish
while children:
pid, status, rusage = os.wait4(-1, 0)
exit_code = os.WEXITSTATUS(status)
print(f"Child {pid} exited after {exit_code} seconds")
children.remove(pid)
print("All children exited")
This creates 5 child processes with random sleep durations. The parent waits for any child to complete using pid=-1, handling them in termination order. The loop continues until all children have exited (children list is empty). This pattern is common in server processes managing multiple workers. Security Considerations
Best Practices
Source ReferencesAuthorMy name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming. List all Python tutorials. |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |