Взаимодействие Python с системой через модуль os
Основные возможности библиотеки os
Наиболее эффективное решение: работа с путями через os.path
Модуль os.path предоставляет функции для кросс-платформенной работы с файловыми путями. Основная цель - избежать ручного склеивания строк, что часто приводит к ошибкам из-за различий разделителей в Windows (обратная косая черта) и Unix (прямая).
import os
# Правильное объединение пути
folder = "data"
file = "report.txt"
full_path = os.path.join(folder, file)
print(full_path) # data/report.txt на Unix, data\report.txt на Windows
# Разделение пути на части
dir_name, base_name = os.path.split(full_path)
print(dir_name) # data
print(base_name) # report.txt
# Получение расширения
name, ext = os.path.splitext(base_name)
print(name) # report
print(ext) # .txtбиблиотека os python (библиотека os для python)
Ошибки часто возникают при попытке передать абсолютный путь с обратной косой чертой на Unix или при использовании конкатенации строк. Рекомендуется всегда использовать os.path.join.
Проблема: если один из компонентов пути содержит разделитель, os.path.join начинает с него. Поэтому не стоит объединять абсолютные и относительные пути без проверки.
print(os.path.join('/home', '/data')) # /data (игнорируется первый компонент)библиотека sys python (библиотека sys в python)
Для проверки существования пути и его типа применяют os.path.exists, os.path.isfile, os.path.isdir:
path = "/tmp/test"
if os.path.exists(path):
if os.path.isfile(path):
print("Это файл")
elif os.path.isdir(path):
print("Это директория")
else:
print("Путь не существует")Такой подход универсален для любой ОС и является базой для работы с файловой системой.
Как получить текущую рабочую директорию?
Функция os.getcwd() возвращает абсолютный путь к текущей рабочей папке. Изменить её можно с помощью os.chdir(path).
import os
current = os.getcwd()
print("Сейчас работаем в:", current)
os.chdir("/tmp")
print("Перешли в", os.getcwd())Ошибка: если указанная директория не существует или нет прав доступа, chdir вызовет FileNotFoundError или PermissionError.
Как создать несколько вложенных директорий за один вызов?
os.makedirs(dir, exist_ok=False) создаёт все промежуточные папки. Если exist_ok=True, ошибка при существовании конечной директории не возникнет.
import os
path = "project/data/2025"
os.makedirs(path, exist_ok=True)
print("Директория", path, "создана или уже существует")Типичная ошибка: вызов os.mkdir для вложенной структуры - он создаёт только один уровень. Если родительская папка отсутствует, возникает FileNotFoundError.
Как рекурсивно обойти все файлы и папки?
os.walk(top) возвращает генератор кортежей (dirpath, dirnames, filenames) для каждого подкаталога.
import os
root = "/tmp/mydata"
for dirpath, dirnames, filenames in os.walk(root):
print("Текущая папка:", dirpath)
for f in filenames:
if f.endswith(".py"):
full = os.path.join(dirpath, f)
print(" Найден .py файл:", full)Важно: os.walk следует по символическим ссылкам на директории, что может привести к зацикливанию. Чтобы избежать этого, используйте параметр followlinks=False.
Как получить переменные окружения?
Словарь os.environ содержит все переменные окружения. Доступ к конкретной - os.environ.get('VAR'). Изменение - os.environ['VAR']='value', но это влияет только на текущий процесс.
import os
home = os.environ.get('HOME', '/tmp')
print("Домашняя папка:", home)
# Добавление новой переменной
os.environ['MY_VAR'] = 'test'
print(os.environ['MY_VAR'])Ошибка: попытка обратиться к несуществующей переменной через os.environ['KEY'] вызывает KeyError. Используйте .get() с значением по умолчанию.
Как выполнить системную команду?
os.system(command) запускает команду в подпроцессе и возвращает код возврата. Для более гибкого управления рекомендуется subprocess, но в простых случаях os.system удобен.
import os
ret = os.system('ls -la')
print("Код возврата:", ret) # 0 - успехПроблема: os.system не захватывает вывод команды. Для получения вывода используйте os.popen (устарел) или subprocess.check_output.
Расширенные примеры использования модуля os
Пример 1: Эффективное сканирование каталогов с os.scandir
Функция os.scandir возвращает итератор объектов DirEntry, который сразу даёт информацию о типе и атрибутах файла без дополнительных системных вызовов. Это быстрее, чем os.listdir с последующими os.stat.
import os
path = "/tmp"
with os.scandir(path) as entries:
for entry in entries:
if entry.is_file() and entry.name.endswith('.txt'):
stat = entry.stat()
print(f"{entry.name}: {stat.st_size} байт, изменён {stat.st_mtime}")файл1.txt: 1024 байт, изменён 1700000000.0 файл2.txt: 2048 байт, изменён 1700000100.0
Пример 2: Передача данных между файловыми дескрипторами через os.sendfile
os.sendfile (доступен в Unix) копирует данные из одного файлового дескриптора в другой на уровне ядра, минуя пользовательское пространство. Используется для высокопроизводительной передачи больших файлов.
import os
src = open('bigfile.bin', 'rb')
dst = open('copy.bin', 'wb')
try:
os.sendfile(dst.fileno(), src.fileno(), 0, 10**6) # копировать 1 МБ
finally:
src.close()
dst.close()
print('Файл скопирован через sendfile')Файл скопирован через sendfile
Пример 3: Получение подробной информации о файле с os.stat
os.stat возвращает объект stat_result с полями st_mode (права и тип), st_uid, st_gid, st_size, st_atime, st_mtime, st_ctime и др. Это полезно для мониторинга и аудита.
import os
import time
file = 'example.py'
if os.path.isfile(file):
s = os.stat(file)
size_kb = s.st_size / 1024
mod_time = time.ctime(s.st_mtime)
print(f"Размер: {size_kb:.2f} КБ")
print(f"Последнее изменение: {mod_time}")
print(f"Права: {oct(s.st_mode & 0o777)}") # маска разрешенийРазмер: 12.34 КБ Последнее изменение: Mon Jan 20 10:15:30 2025 Права: 0o644
Пример 4: Безопасное переименование и замена файлов
os.rename(src, dst) заменяет существующий dst только если операция атомарна (на большинстве файловых систем). os.replace(src, dst) делает это атомарно даже если dst существует, что безопаснее.
import os
old = 'temp.txt'
new = 'final.txt'
# Атомарно заменить final.txt на temp.txt
try:
os.replace(old, new)
print(f"{old} заменён на {new}")
except OSError as e:
print(f"Ошибка: {e}")temp.txt заменён на final.txt
Пример 5: Создание жёстких и символических ссылок
os.link(src, dst) создаёт жёсткую ссылку (на одной файловой системе), os.symlink(src, dst) - символическую. Используется при организации бэкапов или кэшей.
import os
original = 'data.txt'
symlink_name = 'link_to_data'
# Создать символическую ссылку
os.symlink(original, symlink_name)
print("Симлинк создан:", symlink_name)
# Проверить, является ли путь ссылкой
print("Является ли симлинком?", os.path.islink(symlink_name))Симлинк создан: link_to_data Является ли симлинком? True
Пример 6: Изменение прав доступа и владельца
Функции os.chmod(path, mode) и os.chown(path, uid, gid) меняют разрешения и владельца. Требуются соответствующие привилегии.
import os
file = 'private.log'
# Установить права только для владельца (чтение+запись)
os.chmod(file, 0o600)
# Изменить владельца на uid=1000, gid=1000 (если есть права root)
# os.chown(file, 1000, 1000)
print(f"Права изменены: {oct(os.stat(file).st_mode & 0o777)}")Права изменены: 0o600