Complete guide to Python's os.getppid function covering process hierarchy, parent process identification, and practical examples.
Last modified April 11, 2025
This comprehensive guide explores Python’s os.getppid function, which returns the parent process ID (PPID) of the current process. We’ll cover process hierarchy, practical examples, and related system calls.
The os.getppid function returns the process ID of the parent process that created the current process. Every process (except init) has a parent process in Unix-like systems.
Key points: returns integer PPID, available on Unix/Windows, related to os.getpid (current PID). Parent process can terminate while child continues running (orphan process).
This simple example demonstrates how to get both the current process ID and its parent process ID using os.getpid and os.getppid.
basic_usage.py
import os
print(f"Current process ID (PID): {os.getpid()}") print(f"Parent process ID (PPID): {os.getppid()}")
When run directly, this will show the Python interpreter’s PID and the terminal/shell’s PID that launched it. The output will vary each run.
The parent process is typically the shell or process that executed the Python script. This relationship forms a process tree hierarchy.
This example creates a child process to show how parent-child relationships work and how PPID changes in child processes.
process_hierarchy.py
import os import time
def child_process(): print(f"Child PID: {os.getpid()}") print(f"Child’s PPID: {os.getppid()}") time.sleep(2)
def parent_process(): print(f"Parent PID: {os.getpid()}") print(f"Parent’s PPID: {os.getppid()}")
pid = os.fork()
if pid == 0: # Child process
child_process()
else: # Parent process
print(f"Created child with PID: {pid}")
time.sleep(3)
if name == “main”: parent_process()
This Unix-specific example uses os.fork to create a child process. The child reports its PID and PPID (which is the parent’s PID).
Note that Windows doesn’t support os.fork - this example works only on Unix-like systems. The sleep calls prevent premature exit.
This example demonstrates how to detect when a parent process dies, making the child an orphan (adopted by init, PPID becomes 1).
orphan_process.py
import os import time
def child_process(): original_ppid = os.getppid() print(f"Child started with PPID: {original_ppid}")
while True:
current_ppid = os.getppid()
if current_ppid != original_ppid:
print(f"Parent died! New PPID: {current_ppid}")
break
time.sleep(1)
def parent_process(): print(f"Parent PID: {os.getpid()}") pid = os.fork() if pid == 0: # Child child_process() else: # Parent time.sleep(2) print(“Parent exiting”)
if name == “main”: parent_process()
The child process continuously checks its PPID. When the parent exits, the child’s PPID changes to 1 (init process on Unix systems).
This demonstrates how processes can outlive their parents and how the system reassigns orphan processes to maintain process hierarchy.
This example shows a cross-platform way to create processes and examine the parent-child relationship using os.getppid.
cross_platform.py
import os import sys import time from multiprocessing import Process
def child_task(): print(f"Child PID: {os.getpid()}") print(f"Child’s PPID: {os.getppid()}") time.sleep(2)
if name == “main”: print(f"Parent PID: {os.getpid()}")
# Cross-platform process creation
p = Process(target=child_task)
p.start()
print(f"Created child with PID: {p.pid}")
p.join()
print("Parent exiting")
Using multiprocessing.Process instead of os.fork makes this work on both Unix and Windows systems while maintaining the parent-child relationship.
The child process reports its PID and PPID, showing the relationship to the parent process that created it.
This example builds a simple process tree by recursively creating child processes and tracking parent-child relationships.
process_tree.py
import os import time from multiprocessing import Process
def process_node(name, depth): if depth <= 0: return
print(f"{' '*(3-depth)}Node {name}: PID={os.getpid()}, PPID={os.getppid()}")
children = []
for i in range(2): # Create 2 child processes
p = Process(target=process_node, args=(f"{name}.{i}", depth-1))
children.append(p)
p.start()
time.sleep(1) # Wait for children to print their info
for p in children:
p.join()
if name == “main”: process_node(“root”, 3)
This creates a binary tree of processes 3 levels deep, printing each process’s PID and PPID to visualize the hierarchy.
The indentation in the output helps visualize the tree structure. Each process knows its parent through os.getppid.
This example demonstrates how daemon processes maintain their PPID relationship and how it differs from regular processes.
daemon_process.py
import os import time from multiprocessing import Process
def daemon_task(): print(f"Daemon PID: {os.getpid()}, PPID: {os.getppid()}") while True: print(f"Daemon running (PPID: {os.getppid()})") time.sleep(1)
if name == “main”: print(f"Main PID: {os.getpid()}") d = Process(target=daemon_task, daemon=True) d.start()
print(f"Created daemon with PID: {d.pid}")
time.sleep(3)
print("Main process exiting (daemon will terminate)")
Daemon processes are designed to terminate when their parent exits. This example shows the PPID relationship before and during execution.
Unlike the orphan process example, daemons don’t get reassigned to init - they terminate when their parent process exits.
Process spoofing: PPID can potentially be spoofed in some cases
Race conditions: Parent may exit between PPID check and use
Cross-platform: Behavior consistent but implementation differs
Orphan processes: Need special handling if parent dies
Privilege escalation: Inherited privileges from parent process
Check return value: Always handle potential errors
Consider alternatives: For complex hierarchies, use process managers
Document assumptions: Clearly note parent process requirements
Handle parent death: Implement logic for orphan scenarios
Cross-platform testing: Verify behavior on all target systems
My 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.