Библиотека 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 при отсутствии прав.
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)
(без вывода, операция выполнена)