Skip to main content

Modules/posixmodule.c

Source:

cpython 3.14 @ ab2d84fe1023/Modules/posixmodule.c

Modules/posixmodule.c is the C implementation of the os module on POSIX systems (and the nt module on Windows). At ~17,000 lines it is the largest module file in CPython. It wraps every POSIX syscall that Python exposes via os.

Map

LinesSymbolRole
1-600Includes, platform conditionalsOS detection, _Py_stat_struct
601-1500os.stat, os.lstat, os.fstatstat family; stat_result object
1501-2500os.open, os.read, os.write, os.close, os.dupLow-level file I/O
2501-3500os.listdir, os.scandir, ScandirIterDirectory listing
3501-4500os.mkdir, os.makedirs, os.rmdir, os.removedirsDirectory creation/removal
4501-5500os.unlink, os.rename, os.replace, os.link, os.symlinkFile operations
5501-7000os.getcwd, os.chdir, os.chmod, os.chownWorking dir and permissions
7001-9000os.fork, os.exec*, os.waitpid, os.kill, os.getpidProcess management
9001-11000os.environ, os.getenv, os.putenv, os.unsetenvEnvironment variables
11001-17000os.path, xattrs, ioctls, sched, misc POSIXRemaining functions

Reading

stat_result

os.stat() returns a stat_result named tuple with st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid, st_size, st_atime, st_mtime, st_ctime, plus extended fields on some platforms (st_blksize, st_blocks, st_flags).

// CPython: Modules/posixmodule.c:2430 posix_stat_impl
static PyObject *
posix_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
{
struct stat st;
...
result = stat(path->narrow, &st);
...
return _pystat_fromstructstat(module, &st);
}

os.scandir

scandir(path) returns an iterator of DirEntry objects. Unlike listdir, DirEntry caches the file type from readdir's d_type field (on Linux), avoiding a stat call per entry for the common case.

// CPython: Modules/posixmodule.c:14520 ScandirIter_iternext
static PyObject *
ScandirIter_iternext(ScandirIterator *iterator)
{
...
errno = 0;
dirent = readdir(iterator->dirp);
if (!dirent) { ... }
entry = DirEntry_from_posix_info(iterator->module, path, dirent->d_name,
dirent->d_ino, dirent->d_type);
...
}

os.fork and os.exec*

os.fork() wraps fork(2). After fork, CPython reinitializes internal state (lock counts, cached file descriptors) in the child via _PyOS_AfterFork_Child. The exec* family (execv, execve, execvp) wraps the corresponding POSIX calls after converting Python argument lists to char**.

os.environ

os.environ is a _Environ object (a MutableMapping subclass) backed by the process environment. Reads call getenv; writes call putenv. It is populated lazily from environ at first access.

gopy notes

Status: partially ported via module/sys/module.go and direct Go os package calls. The gopy os module wraps Go's os.Stat, os.ReadDir, os.Mkdir, os.Remove, os.Rename, os.Getwd, and os.Chdir. Process-management functions (fork, exec, waitpid) are low-priority due to the GIL-free goroutine model.