The fcntl and ioctl System Calls in Python

The fcntl module in Python provides an interface to the fcntl() and ioctl() Unix system calls for file control operations. This module is essential for low-level file descriptor manipulation, file locking, and I/O control operations on Unix-like systems.

All methods in this module take a file descriptor (integer) or io.IOBase object as their first argument. To use this module, import it first:

import fcntl

fcntl.fcntl(fd, op[, arg]) Method

This method performs operations on file descriptors. The op parameter defines the operation, and the optional arg can be an integer or string. When arg is an integer, it returns the C fcntl() call result. When it's a string, it represents a binary structure. Raises IOError on failure.

import fcntl
import os

# Open a file and get its descriptor
with open('test.txt', 'w') as f:
    # Get file descriptor flags
    flags = fcntl.fcntl(f.fileno(), fcntl.F_GETFL)
    print(f"File flags: {flags}")

fcntl.ioctl(fd, op[, arg[, mutate_flag]]) Method

Similar to fcntl() but with more complex argument handling. The mutate_flag parameter controls whether a mutable buffer can be modified. When True, the buffer is mutable; otherwise, it acts as read-only.

fcntl.flock(fd, op) Method

Performs file locking operations using the file descriptor. Common operations include:

  • LOCK_SH − Shared lock

  • LOCK_EX − Exclusive lock

  • LOCK_NB − Non-blocking lock

  • LOCK_UN − Unlock

fcntl.lockf(fd, operation[, length[, start[, whence]]]) Method

A wrapper around POSIX locking calls with these operations:

  • LOCK_UN − Unlock the file

  • LOCK_SH − Shared lock

  • LOCK_EX − Exclusive lock

File Locking Example

Here's a practical example demonstrating file locking to safely increment a counter ?

import fcntl
import os
import time

counter_file = 'my_counter.txt'

# Create counter file if it doesn't exist
if not os.path.exists(counter_file):
    with open('my_counter.txt', 'w') as f:
        f.write('0')  # Store 0 as starting number

# Increment counter 15 times with file locking
for i in range(15):
    with open('my_counter.txt', 'r+') as f:
        # Acquire exclusive lock
        fcntl.flock(f.fileno(), fcntl.LOCK_EX)
        
        # Read current count and increment
        count = int(f.readline()) + 1
        
        # Write new count back to file
        f.seek(0)
        f.write(str(count))
        f.truncate()  # Remove any leftover content
        
        print(f'Process ID: {os.getpid()}, Count: {count}')
    
    # File is automatically unlocked when closed
    time.sleep(0.2)
Process ID: 12698, Count: 1
Process ID: 12698, Count: 2
Process ID: 12698, Count: 3
Process ID: 12698, Count: 4
Process ID: 12698, Count: 5
Process ID: 12698, Count: 6
Process ID: 12698, Count: 7
Process ID: 12698, Count: 8
Process ID: 12698, Count: 9
Process ID: 12698, Count: 10
Process ID: 12698, Count: 11
Process ID: 12698, Count: 12
Process ID: 12698, Count: 13
Process ID: 12698, Count: 14
Process ID: 12698, Count: 15

Key Points

  • The fcntl module is Unix-specific and not available on Windows

  • File locking prevents race conditions in concurrent file access

  • Always handle IOError exceptions when using fcntl operations

  • Use context managers (with statements) for automatic file closure and lock release

Conclusion

The fcntl module provides essential file control and locking capabilities for system-level programming in Python. Use flock() for file locking and fcntl() for general file descriptor operations to ensure safe concurrent file access.

Updated on: 2026-03-25T04:51:15+05:30

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements