Библиотека os для работы с файлами: полный обзор возможностей

Раздел: Стандартная библиотека Python -> Стандартная библиотека os

Работа с файлами и каталогами через модуль os

Основной подход: комбинация os.path и os для типовых операций

Наиболее эффективное решение для работы с файлами предполагает совместное использование функций os (создание, удаление, переименование) и методов модуля os.path (проверка существования, получение атрибутов, работа с путями). Это позволяет писать кроссплатформенный код, избегая ручного конкатенации строк.

import os
# Пример: создание вложенной папки, если она не существует
path = 'data/2025/reports'
if not os.path.exists(path):
    os.makedirs(path)
    print('Папка создана:', path)
else:
    print('Папка уже существует')

библиотека os python файлы (библиотека os для работы с файлами в python)

Папка создана: data/2025/reports

Комментарий: os.makedirs создаёт все промежуточные каталоги. Проверка os.path.exists предотвращает ошибку FileExistsError.

Типичные проблемы:

  • FileExistsError при попытке создать уже существующую директорию (решение: проверять существование или использовать параметр exist_ok=True в os.makedirs).
  • Ошибки из-за символических ссылок: os.path.exists возвращает True для битых ссылок? На самом деле os.path.exists возвращает False для битых ссылок, а os.path.lexists - True.
  • Проблемы с правами доступа: PermissionError при отсутствии прав на запись.

Как проверить, является ли объект файлом или папкой?

Используйте os.path.isfile и os.path.isdir. Они возвращают True только для существующих объектов.

import os
path = 'example.txt'
if os.path.isfile(path):
    print('Это файл')
elif os.path.isdir(path):
    print('Это папка')
else:
    print('Объект не существует или не является файлом/папкой')

Ошибка:

os.path.isfile может вернуть False для файла, если у пользователя нет прав на чтение родительского каталога. В этом случае лучше обработать исключение PermissionError.

Как получить список файлов в каталоге и обработать каждый?

Используйте os.listdir для простого перечисления или os.scandir (быстрее, возвращает объекты DirEntry с метаданными).

import os
# Вариант 1: listdir
for name in os.listdir('.'):
    path = os.path.join('.', name)
    if os.path.isfile(path):
        print('Файл:', name)

# Вариант 2: scandir (рекомендуется)
with os.scandir('.') as entries:
    for entry in entries:
        if entry.is_file():
            print('Файл:', entry.name, 'размер:', entry.stat().st_size)

Проблема:

os.listdir не предоставляет информацию о типе объекта – требуется дополнительный вызов stat. os.scandir решает эту проблему.

Как рекурсивно обойти все подкаталоги и файлы?

Используйте os.walk, который генерирует кортежи (root, dirs, files).

import os
for root, dirs, files in os.walk('.'):
    for file in files:
        full_path = os.path.join(root, file)
        print(f'Файл: {full_path}, размер: {os.path.getsize(full_path)}')

Ошибка:

При большом количестве файлов os.walk может быть медленным. Для ускорения используйте os.scandir в комбинации с рекурсивным обходом (но os.walk уже оптимизирован). Также остерегайтесь бесконечной рекурсии при символических ссылках на родительские каталоги.

Как переименовать или переместить файл?

Функция os.rename(source, dest) переименовывает или перемещает (если dest в другой папке). Для атомарной замены используйте os.replace.

import os
os.rename('old_name.txt', 'new_name.txt')
os.replace('source/file.txt', 'dest/file.txt')  # замена существующего

Проблемы:

  • FileNotFoundError, если исходный файл не существует.
  • PermissionError при недостаточных правах.
  • Cross-device link error при перемещении между разными файловыми системами – используйте shutil.move.

Как удалить файл или пустую папку?

os.remove удаляет файл, os.rmdir – только пустую папку. Для удаления непустой папки используйте shutil.rmtree.

import os
os.remove('temp.txt')           # удаление файла
os.rmdir('empty_folder')        # удаление пустой папки
# удаление непустой папки:
import shutil
shutil.rmtree('non_empty_folder')

Ошибки:

  • FileNotFoundError, если файла нет.
  • OSError при попытке удалить непустую папку через os.rmdir.

Как получить информацию о файле (размер, время создания/изменения)?

os.stat(path) возвращает объект stat_result с полями st_size, st_mtime, st_ctime. Либо используйте os.path.getsize, os.path.getmtime.

import os
import time
st = os.stat('example.txt')
print('Размер:', st.st_size, 'байт')
print('Последнее изменение:', time.ctime(st.st_mtime))

Ошибка:

FileNotFoundError для несуществующего пути. Обрабатывайте исключение.

Как правильно соединять пути, чтобы код работал на Windows и Linux?

Используйте os.path.join – он подставляет нужный разделитель (обратный слеш на Windows, прямой на Linux).

import os
path = os.path.join('folder', 'sub', 'file.txt')
print(path)  # folder/sub/file.txt на Linux, folder\sub\file.txt на Windows

Проблема:

При работе с абсолютными путями на Windows, os.path.join не добавляет корень диска. Для полного пути используйте os.path.abspath.

Как получить абсолютный путь или нормализовать относительный?

os.path.abspath превращает относительный путь в абсолютный. os.path.normpath удаляет лишние разделители и ..

import os
print(os.path.abspath('.'))          # /home/user/project
print(os.path.normpath('folder/../data/./file.txt'))  # data/file.txt

Как разбить путь на компоненты (базовое имя, директория, расширение)?

os.path.basename, os.path.dirname, os.path.splitext.

import os
path = '/home/user/data/archive.tar.gz'
print(os.path.basename(path))    # archive.tar.gz
print(os.path.dirname(path))     # /home/user/data
print(os.path.splitext(path))    # ('/home/user/data/archive.tar', '.gz')

Замечание:

os.path.splitext разделяет по последней точке, поэтому для двойных расширений (.tar.gz) используйте split с os.extsep.

Как получить текущую рабочую директорию и сменить её?

os.getcwd() и os.chdir(path).

import os
cwd = os.getcwd()
print('Текущая:', cwd)
os.chdir('..')
print('Новая:', os.getcwd())

Ошибки:

FileNotFoundError, если целевая папка не существует. PermissionError при отсутствии прав.

Расширенные примеры работы с os для файловых операций
Пример
import os
import stat
import time

# 1) Рекурсивное копирование каталога с помощью os (альтернатива shutil.copytree)
def copy_tree(src, dst):
    if not os.path.exists(dst):
        os.makedirs(dst)
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            copy_tree(s, d)
        else:
            with open(s, 'rb') as f_in:
                with open(d, 'wb') as f_out:
                    f_out.write(f_in.read())
    # сохраняем права доступа (необязательно)
    shutil.copystat(src, dst)  # требует import shutil

copy_tree('source_folder', 'backup_folder')
print('Копирование завершено.')
Копирование завершено.

Пояснение:

Пример использует рекурсивный обход os.listdir и ручное копирование файлов. Обратите внимание на os.makedirs для создания вложенных папок. Для сохранения метаданных используется shutil.copystat.

Пример
# 2) Получение размера всех файлов в дереве каталогов (суммарно)
import os

total_size = 0
for root, dirs, files in os.walk('.'):
    for file in files:
        file_path = os.path.join(root, file)
        try:
            total_size += os.path.getsize(file_path)
        except OSError:
            pass  # пропускаем файлы с ошибками доступа

print('Суммарный размер:', total_size, 'байт')
Суммарный размер: 2456783 байт
Пример
# 3) Переименование всех файлов с изменением расширения (например, .txt -> .md)
import os

directory = '.'
for file in os.listdir(directory):
    if file.endswith('.txt'):
        base = os.path.splitext(file)[0]
        new_name = base + '.md'
        os.rename(os.path.join(directory, file), os.path.join(directory, new_name))
        print(f'Переименован: {file} -> {new_name}')
Переименован: notes.txt -> notes.md
Переименован: readme.txt -> readme.md
Пример
# 4) Работа с символическими ссылками (создание, чтение цели)
import os

# создание символической ссылки (требуются права)
os.symlink('target.txt', 'link_to_target')
# проверка, является ли объект ссылкой
print('Является ссылкой:', os.path.islink('link_to_target'))
# чтение цели ссылки
if os.path.islink('link_to_target'):
    print('Цель:', os.readlink('link_to_target'))
# удаление ссылки (не удаляет целевой файл)
os.unlink('link_to_target')
Является ссылкой: True
Цель: target.txt
Пример
# 5) Использование os.scandir для быстрого сбора информации
import os

directory = '.'
entries = []
with os.scandir(directory) as it:
    for entry in it:
        if entry.is_file() and entry.name.endswith('.py'):
            st = entry.stat()
            entries.append((entry.name, st.st_size, st.st_mtime))
entries.sort(key=lambda x: x[2], reverse=True)  # сортировка по времени изменения
for name, size, mtime in entries[:5]:
    print(f'{name}: {size} Б, изменён {time.ctime(mtime)}')
main.py: 2341 Б, изменён Tue Jan 14 10:30:00 2025
utils.py: 1567 Б, изменён Mon Jan 13 09:15:20 2025
Пример
# 6) Получение информации о дисковом пространстве (os.statvfs на Unix, os.disk_usage на Python 3.3+)
import os

# os.disk_usage (доступна с Python 3.3)
usage = os.disk_usage('/')
print('Всего:', usage.total // (1024**3), 'ГБ')
print('Использовано:', usage.used // (1024**3), 'ГБ')
print('Свободно:', usage.free // (1024**3), 'ГБ')
Всего: 256 ГБ
Использовано: 120 ГБ
Свободно: 136 ГБ
Пример
# 7) Удаление файлов старше определённого возраста
import os
import time

max_age = 30 * 24 * 3600  # 30 дней в секундах
now = time.time()
for file in os.listdir('.'):
    if os.path.isfile(file):
        age = now - os.path.getmtime(file)
        if age > max_age:
            os.remove(file)
            print('Удалён:', file)
Удалён: old_log.txt
Удалён: temp_backup.zip
Пример
# 8) Смена владельца/группы файла (только Unix)
import os
import pwd

# изменить владельца на пользователя 'www-data'
uid = pwd.getpwnam('www-data').pw_uid
gid = pwd.getgrnam('www-data').gr_gid
os.chown('file.html', uid, gid)
# изменить права доступа (например, 0o644)
os.chmod('file.html', 0o644)
(без вывода, операция выполнена)

Библиотека os для работы с файлами в Python - comments

En
библиотека os python файлы (python)