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 эта особенность может не работать корректно для некоторых символов.
Расширенные примеры работы с путями в 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']