Last modified April 11, 2025
This comprehensive guide explores Python's os.getpgrp function,
which retrieves the process group ID of the current process. We'll cover Unix
process groups, session management, and practical examples.
The os.getpgrp function returns the process group ID of the
current process. Process groups are used by Unix systems to manage job control.
A process group is a collection of related processes that can receive signals as a unit. The process group ID is typically the PID of the group leader.
The simplest use of os.getpgrp retrieves the current process's
group ID. This example shows basic usage and compares it with the process ID.
import os
# Get current process group ID
pgrp = os.getpgrp()
pid = os.getpid()
print(f"Process ID: {pid}")
print(f"Process Group ID: {pgrp}")
# Check if process is group leader
if pid == pgrp:
print("This process is the group leader")
else:
print("This process is not the group leader")
This example shows the relationship between process ID and process group ID. When they match, the process is the group leader.
New processes typically inherit their parent's process group unless explicitly
changed with os.setpgrp or similar functions.
This example demonstrates how process groups are inherited when creating child
processes using os.fork.
import os
print(f"Parent PID: {os.getpid()}, PGID: {os.getpgrp()}")
child_pid = os.fork()
if child_pid == 0:
# Child process
print(f"Child PID: {os.getpid()}, PGID: {os.getpgrp()}")
else:
# Parent process
os.waitpid(child_pid, 0)
The child process inherits the parent's process group by default. Both processes will show the same process group ID in the output.
This behavior is fundamental to Unix process management and job control mechanisms.
This example shows how to create a new process group using os.setpgrp
and verify it with os.getpgrp.
import os
print(f"Original PGID: {os.getpgrp()}")
# Create new process group
os.setpgrp()
print(f"New PGID: {os.getpgrp()}")
# Verify we're now the group leader
if os.getpid() == os.getpgrp():
print("Successfully created new process group")
else:
print("Failed to create new process group")
After calling os.setpgrp, the process becomes leader of a new
process group with its PID as the group ID.
This is commonly done by shell programs when starting new job control sessions.
This example demonstrates how process groups relate to terminal control and signal handling.
import os
import signal
import time
def handler(signum, frame):
print(f"Received signal {signum} in process {os.getpid()}")
# Set up signal handler
signal.signal(signal.SIGINT, handler)
print(f"Process {os.getpid()} in group {os.getpgrp()}")
# Fork a child process
child_pid = os.fork()
if child_pid == 0:
# Child process
print(f"Child {os.getpid()} in group {os.getpgrp()}")
time.sleep(10)
else:
# Parent process
print(f"Parent {os.getpid()} waiting")
os.waitpid(child_pid, 0)
Run this script and press Ctrl+C to see how the signal is delivered to both processes in the same group.
Process groups determine which processes receive terminal-generated signals like SIGINT (Ctrl+C) and SIGTSTP (Ctrl+Z).
This advanced example demonstrates process groups in the context of session
management, showing how os.getpgrp relates to session IDs.
import os
def print_ids():
print(f"PID: {os.getpid()}")
print(f"PGID: {os.getpgrp()}")
print(f"SID: {os.getsid(0)}")
print()
print("Original process:")
print_ids()
# Create new session
if os.fork() == 0:
os.setsid()
print("After setsid():")
print_ids()
os._exit(0)
os.wait()
The child process creates a new session with os.setsid, becoming
both session leader and process group leader.
Note that os.setsid also creates a new process group automatically.
This example simulates how shells manage process groups for job control, demonstrating foreground and background process groups.
import os
import time
def worker(name):
print(f"{name} PID: {os.getpid()}, PGID: {os.getpgrp()}")
time.sleep(5)
# Simulate shell job control
print(f"Shell PID: {os.getpid()}, PGID: {os.getpgrp()}")
# Create foreground process group
foreground = os.fork()
if foreground == 0:
worker("Foreground")
os._exit(0)
# Create background process group
background = os.fork()
if background == 0:
os.setpgrp()
worker("Background")
os._exit(0)
os.waitpid(foreground, 0)
os.waitpid(background, 0)
The example shows how shells typically create separate process groups for foreground and background jobs.
Background jobs get their own process group to prevent them from receiving terminal signals meant for foreground processes.
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.