os.path: работа с путями во второй версии Python

Раздел: Системное администрирование -> Файловый ввод-вывод

Методы модуля os.path для работы с путями в Python 2

Как получить абсолютный путь к файлу и проверить его существование в Python 2?

Основное решение

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

import os

relative_path = "data/config.txt"
abs_path = os.path.abspath(relative_path)
print("Абсолютный путь:", abs_path)
print("Файл существует?", os.path.exists(abs_path))

ввод программ на python (ввод данных в программе python)

Абсолютный путь: /home/user/data/config.txt
Файл существует? True

Python file io (ввод-вывод файлов в python)

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

  • os.path.exists() возвращает True как для файлов, так и для каталогов. Если нужно различать, следует применять os.path.isfile() или os.path.isdir().
  • В Windows пути могут содержать букву диска и обратную косую черту. os.path.abspath() корректно преобразует относительные пути с учётом текущего диска.
  • При работе с Unicode-именами файлов в старых версиях Python 2 возможны исключения UnicodeDecodeError. Рекомендуется использовать строки unicode и кодировку файловой системы.

Как объединить и нормализовать части пути в Python 2?

Для создания полного пути из частей используется os.path.join(). Он автоматически добавляет правильный разделитель (os.sep). os.path.normpath() удаляет лишние разделители и нормализует точки.

import os

base = "/var/log"
subdir = "nginx"
filename = "access.log"
full_path = os.path.join(base, subdir, filename)
print("Объединённый путь:", full_path)
print("Нормализованный:", os.path.normpath("/var//log/./nginx/../nginx/access.log"))

Python temp files (временные файлы в python)

Объединённый путь: /var/log/nginx/access.log
Нормализованный: /var/log/nginx/access.log

Python index files (индексация файлов в python)

Проблемы

Если в os.path.join() передать аргумент, начинающийся с разделителя, предыдущие части игнорируются. Это может привести к неожиданным результатам. Например, os.path.join("/usr", "/bin") вернёт "/bin".

Как разбить путь на части: родительский каталог и имя файла?

os.path.split() возвращает кортеж из двух элементов - директория и имя файла. os.path.dirname() и os.path.basename() делают то же по отдельности.

import os

path = "/etc/ssh/sshd_config"
dirname, basename = os.path.split(path)
print("Директория:", dirname)
print("Имя файла:", basename)
print("Только директория:", os.path.dirname(path))
print("Только имя:", os.path.basename(path))

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

Директория: /etc/ssh
Имя файла: sshd_config
Только директория: /etc/ssh
Только имя: sshd_config

Python file utf 8 (кодировка utf-8 для файлов в python)

Особенности

Если путь оканчивается на разделитель, os.path.basename() может вернуть пустую строку. Следует предварительно применять os.path.normpath() или проверять наличие завершающего слеша.

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

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

import os

link_path = "/usr/bin/python2"  # может быть символьной ссылкой
real = os.path.realpath(link_path)
print("Реальный путь:", real)

Python config files (конфигурационные файлы в python)

Реальный путь: /usr/bin/python2.7

Python copy file (копирование файла в python)

Ошибки

Если ссылка ведёт в несуществующий путь, os.path.realpath() вернёт путь без разрешения. В Python 2 нет возможности проверить, разрешилась ли ссылка полностью, поэтому рекомендуется дополнительно вызывать os.path.exists().

Как работать с домашними каталогами и переменными окружения в путях?

Функции os.path.expanduser() и os.path.expandvars() заменяют ~ на путь к домашнему каталогу пользователя и $VAR на значение переменной окружения соответственно.

import os

path = "~/.ssh/id_rsa"
expanded = os.path.expanduser(path)
print("С ~:", expanded)

path_with_var = "$HOME/.config"
expanded = os.path.expandvars(path_with_var)
print("С переменной:", expanded)

Python log file (логирование в файл в python)

С ~: /home/user/.ssh/id_rsa
С переменной: /home/user/.config

Проблемы

В Windows os.path.expanduser() распознаёт ~ только если задана переменная HOME или USERPROFILE. os.path.expandvars() поддерживает синтаксис %VAR% на Windows, но в Python 2 эта особенность может не работать корректно для некоторых символов.

- File handle python (обработка файлов в python)
- Python open file read (открытие файла для чтения в python)
- Python file position (позиционирование в файле python)

Расширенные примеры работы с путями в Python 2

В этом разделе приведены более сложные сценарии, которые часто встречаются в системном администрировании.

Рекурсивный обход каталогов с помощью os.walk

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

Пример
import os

def count_files(root_dir):
    total = 0
    for root, dirs, files in os.walk(root_dir):
        total += len(files)
    return total

root = "/var/log"
print("Всего файлов в", root, ":", count_files(root))
Всего файлов в /var/log : 142

Ошибки при обходе

Если в дереве есть недоступные для чтения каталоги, возникнет исключение OSError. Рекомендуется оборачивать вызов в блок try-except или использовать обработчик ошибок в os.walk (параметр onerror не поддерживается в Python 2.5-).

Получение относительного пути между двумя абсолютными путями

В Python 2.6 появилась функция os.path.relpath(), которая возвращает относительный путь от одного каталога до другого.

Пример
import os

start = "/home/user/docs"
target = "/home/user/docs/projects/python/script.py"
rel = os.path.relpath(target, start)
print("Относительный путь:", rel)
Относительный путь: projects/python/script.py

Создание файла только если родительская директория существует

При добавлении нового файла полезно проверить существование родительского каталога и создать его при необходимости.

Пример
import os

def safe_create_file(filepath):
    dirname = os.path.dirname(filepath)
    if not os.path.exists(dirname):
        os.makedirs(dirname)
    open(filepath, 'a').close()  # создаёт пустой файл

safe_create_file("/tmp/test/subdir/config.ini")
print("Файл создан, существует?", os.path.exists("/tmp/test/subdir/config.ini"))
Файл создан, существует? True

Разрешение последовательности ссылок с проверкой циклов

В сложных файловых системах символьные ссылки могут образовывать циклы. Пример функции, которая разрешает ссылки, избегая бесконечного цикла.

Пример
import os

def realpath_safe(path, seen=None):
    if seen is None:
        seen = set()
    if path in seen:
        return path  # цикл обнаружен
    seen.add(path)
    if os.path.islink(path):
        link_target = os.readlink(path)
        if not os.path.isabs(link_target):
            link_target = os.path.join(os.path.dirname(path), link_target)
        return realpath_safe(link_target, seen)
    return os.path.abspath(path)

link = "/tmp/loop_link"
if not os.path.exists(link):
    os.symlink("/tmp/loop_link", link)  # искусственный цикл
result = realpath_safe(link)
print("Результат с защитой от цикла:", result)
Результат с защитой от цикла: /tmp/loop_link

Работа с разделителями путей в разных операционных системах

Атрибут os.sep содержит разделитель, используемый в текущей ОС ( / на Unix, \ на Windows). Пример сборки пути вручную с проверкой.

Пример
import os

def make_path(*parts):
    return os.sep.join(parts)

path = make_path("usr", "local", "bin")
print("Собранный путь:", path)
print("Текущий разделитель:", repr(os.sep))
Собранный путь: usr/local/bin
Текущий разделитель: '/'

Примечание

На Windows результат будет содержать обратную косую черту. Использование os.path.join() предпочтительнее, так как он учитывает особенности кодировки и проверяет корректность.

Получение списка файлов с определённым расширением в каталоге

Комбинация os.listdir() и os.path.splitext() позволяет отфильтровать файлы по расширению.

Пример
import os

def find_files_with_ext(directory, ext):
    result = []
    for f in os.listdir(directory):
        full = os.path.join(directory, f)
        if os.path.isfile(full) and os.path.splitext(f)[1] == ext:
            result.append(f)
    return result

print("Файлы .py в текущем каталоге:", find_files_with_ext(".", ".py"))
Файлы .py в текущем каталоге: ['example.py', 'main.py']

Путь к Python 2 - comments

En
Path python 2 (python)