Основы работы с операционной системой через Python os

Раздел: Основы Python -> Работа с операционной системой

Основные функции модуля os

Наиболее эффективный способ работы с файловой системой в Python - комбинировать функции os.path и os. Модуль os предоставляет интерфейс для взаимодействия с операционной системой, а подмодуль os.path содержит удобные методы для манипуляции путями. Основные задачи: получение текущей директории, создание папок, проверка наличия файлов, построение корректных путей.

import os

# Получить текущий рабочий каталог
current_dir = os.getcwd()
print(f'Текущая директория: {current_dir}')

# Построить путь к файлу в подпапке
base_path = '/home/user/projects'
file_path = os.path.join(base_path, 'data', 'config.json')
print(f'Полный путь: {file_path}')

# Проверить существование
if os.path.exists(file_path):
    print('Файл существует')
else:
    print('Файл не найден')

# Создать вложенные папки (аналог mkdir -p)
os.makedirs('/tmp/test/deep/nested', exist_ok=True)

Python os (модуль os в python)

Ключевые преимущества такого подхода - кроссплатформенность (правильные разделители путей) и избежание проблем с жёстким кодированием.

Как узнать текущий рабочий каталог?

Для получения текущей директории используется os.getcwd(). Результат может измениться после вызова os.chdir().

import os

original = os.getcwd()
os.chdir('/tmp')
print('Текущая после смены:', os.getcwd())
os.chdir(original)  # Вернуться назад

Проблема: если передан несуществующий путь в os.chdir, возникает FileNotFoundError. Решение - перед сменой проверить существование пути через os.path.isdir().

if os.path.isdir('/tmp/existing'):
    os.chdir('/tmp/existing')
else:
    print('Директория не существует')

Как создать вложенные папки одной командой?

Функция os.makedirs() создает все недостающие промежуточные директории, аналогично команде mkdir -p. Параметр exist_ok=True предотвращает ошибку, если папка уже существует.

import os

os.makedirs('/tmp/level1/level2/level3', exist_ok=True)
print('Папки созданы')

Проблема: если у пользователя недостаточно прав для создания хотя бы одной из директорий, возникает PermissionError. Также может возникнуть OSError при попытке создать папку в файловой системе с ограничениями. Решение - обернуть вызов в try-except и обработать конкретные исключения.

try:
    os.makedirs('/usr/local/test', exist_ok=True)
except PermissionError:
    print('Недостаточно прав для создания')
except OSError as e:
    print(f'Ошибка: {e}')

Как выполнить системную команду и получить ее вывод?

Хотя os.system() позволяет выполнить команду, для получения вывода и управления ошибками лучше использовать модуль subprocess. Однако в контексте модуля os можно применить os.popen() для чтения вывода.

import os

# Запуск команды и чтение вывода
with os.popen('ls -la /tmp') as pipe:
    output = pipe.read()
    print(output)

Проблема: os.system() не возвращает вывод, только код возврата. os.popen() устарел и может вести себя непредсказуемо в многопоточных сценариях. Рекомендуется использовать subprocess.run().

import subprocess
result = subprocess.run(['ls', '-la', '/tmp'], capture_output=True, text=True)
print(result.stdout)

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

Функция os.walk() генерирует имена файлов в дереве каталогов, обходя подпапки автоматически.

import os

for root, dirs, files in os.walk('/tmp'):
    for file in files:
        if file.endswith('.txt'):
            full_path = os.path.join(root, file)
            print(full_path)

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

import os

for root, dirs, files in os.walk('/'):
    # Пропустить папки, к которым нет доступа
    dirs[:] = [d for d in dirs if os.access(os.path.join(root, d), os.R_OK)]
    for file in files:
        print(os.path.join(root, file))

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

Функция os.rename() изменяет имя или перемещает файл (если целевой путь находится в другой файловой системе, может произойти ошибка). В современных версиях Python рекомендуется os.replace(), который атомарно заменяет целевой файл.

import os

os.rename('/tmp/old.txt', '/tmp/new.txt')  # перемещение внутри раздела
os.replace('/tmp/source.txt', '/tmp/target.txt')  # замена существующего

Проблема: если целевой файл уже существует, os.rename() вызывает FileExistsError (в некоторых ОС). os.replace() не выдает ошибку, а перезаписывает. При перемещении между разными разделами диска возникает OSError. Решение - использовать shutil.move() для кроссплатформенного перемещения.

import shutil

try:
    shutil.move('/tmp/myfile.bin', '/mnt/usb/myfile.bin')
except OSError as e:
    print(f'Не удалось переместить: {e}')

Расширенные примеры работы с модулем os

1. Использование os.scandir для получения метаданных

Функция os.scandir() возвращает итератор объектов DirEntry, содержащих имя, тип (файл/папка) и статистику, что быстрее, чем os.listdir() с последующими вызовами os.path.isdir().

Пример
import os

with os.scandir('/tmp') as entries:
    for entry in entries:
        if entry.is_file():
            size = entry.stat().st_size
            print(f'{entry.name}: {size} байт')
tempfile.txt: 1024 байт
log.log: 256 байт

2. Рекурсивное копирование дерева папок без shutil

Используя os.walk() и os.makedirs(), можно реализовать копирование структуры каталогов, создавая целевые папки и копируя файлы с помощью shutil.copy2.

Пример
import os
import shutil

def copy_tree(src, dst):
    for root, dirs, files in os.walk(src):
        # Создать относительный путь от src
        rel_path = os.path.relpath(root, src)
        dest_path = os.path.join(dst, rel_path)
        os.makedirs(dest_path, exist_ok=True)
        for file in files:
            src_file = os.path.join(root, file)
            dest_file = os.path.join(dest_path, file)
            shutil.copy2(src_file, dest_file)

copy_tree('/path/source', '/path/destination')
(пусто при успешном выполнении)

3. Получение информации об операционной системе

Модуль os содержит функции для получения идентификатора текущего пользователя, количества процессоров, имени ядра и платформы.

Пример
import os

print('Имя пользователя:', os.getlogin())
print('Количество CPU:', os.cpu_count())
print('ОС:', os.name)
print('Информация о платформе:', os.uname())
Имя пользователя: user
Количество CPU: 8
ОС: posix
Информация о платформе: (sysname='Linux', nodename='host', release='6.2.0-35-generic', version='#36-Ubuntu SMP', machine='x86_64')

4. Работа с переменными окружения

Доступ к переменным окружения осуществляется через словарь os.environ. Рекомендуется использовать os.environ.get() для безопасного чтения.

Пример
import os

# Чтение с умолчанием
home = os.environ.get('HOME', '/home/default')
print('Домашний каталог:', home)

# Установка своей переменной
os.environ['MY_APP_MODE'] = 'production'
print('Режим:', os.environ.get('MY_APP_MODE'))

# Удаление
del os.environ['MY_APP_MODE']
Домашний каталог: /home/user
Режим: production

5. Разбор пути: os.path.split и os.path.splitext

Эти функции разделяют путь на компоненты: директорию и имя файла, а также отделяют расширение.

Пример
import os

full_path = '/home/user/docs/report.pdf'
dir_name, file_name = os.path.split(full_path)
print('Папка:', dir_name)
print('Файл:', file_name)

base, ext = os.path.splitext(file_name)
print('Имя без расширения:', base)
print('Расширение:', ext)
Папка: /home/user/docs
Файл: report.pdf
Имя без расширения: report
Расширение: .pdf

6. os.path.realpath vs os.path.abspath с символическими ссылками

os.path.abspath() просто добавляет текущую директорию к относительному пути, а os.path.realpath() разрешает все ссылки и возвращает канонический путь.

Пример
import os

# Предположим, /tmp/link -> /var/data
print('Абсолютный путь:', os.path.abspath('/tmp/link'))
print('Реальный путь:', os.path.realpath('/tmp/link'))
Абсолютный путь: /tmp/link
Реальный путь: /var/data

7. Управление процессами: os.getpid и os.kill

Можно получить идентификатор текущего процесса и отправить сигнал другому процессу (только в Unix-подобных системах).

Пример
import os
import signal

print('PID текущего процесса:', os.getpid())

# Отправить сигнал SIGTERM процессу с PID 1234
# os.kill(1234, signal.SIGTERM)
PID текущего процесса: 16782

Модуль os в Python - comments

En
Python os (python)