Путь к файлам в Python
Для работы с файловой системой в Python используют модули os, os.path и shututil, а для операций с файлами – встроенные функции open(), close(), read(), readline(), write() и т. д. Прежде, чем мы перейдем к примерам использования конкретных методов, отметим один важный момент – корректный формат пути к файлам и каталогам.
Дело в том, что Python считает некорректным стандартный
для Windows формат: если указать путь к файлу в привычном виде 'C:\Users\User\Python\letters.py'
, интерпретатор вернет ошибку. Лучше
всего указывать путь с помощью r-строк
или с экранированием слэшей:
r'C:\Users\User\Python\letters.py'
'C:\\Users\\User\\Python\\letters.py'
Иногда также путь указывают с обратными слэшами:
'C:/Users/User/Python/letters.py'
Получение информации о файлах и директориях
Метод getcwd() возвращает путь к текущей рабочей директории в виде строки:
>>> import os
>>> os.getcwd()
'C:\\Users\\User\\Python'
С помощью метода os.listdir() можно получить список всех поддиректорий и файлов текущего рабочего каталога, при этом содержимое вложенных папок не отображается:
>>> os.listdir()
['Data', 'lambda_functions.py', 'letters.py', 'os_methods.py', 'passw_generator.py', 'points.py', 'population.py']
Метод os.walk() возвращает генератор, в котором содержится вся информация о рабочем каталоге, включая содержимое всех поддиректорий:
>>> import os
>>> my_cwd = os.getcwd()
>>> result = os.walk(my_cwd)
>>> for i, j, k in result:
for file in k:
print(file)
lambda_functions.py
letters.py
os_methods.py
passw_generator.py
points.py
population.py
books_to_process.txt
challenge_data.txt
ledger.txt
Много полезных методов содержится в модуле os.path. Так можно извлечь имя файла из полного пути:
>>> os.path.basename(r'C:\Users\User\Python\letters.py')
'letters.py'
А так можно получить путь к директории / файлу, в который не включается собственно поддиректория или имя файла:
>>> os.path.dirname(r'C:\Users\User\Python\Data')
'C:\\Users\\User\\Python'
Метод path.isabs() покажет, является ли путь абсолютным или относительным:
>>> os.path.isabs(r'C:\Users\User\Python\Data')
True
>>> os.path.isabs(r'.\Python\Data')
False
>>>
Метод path.isdir() возвращает True
, если переданная в метод директория существует, и False
– в противном случае:
>>> os.path.isdir(r'C:\Users\User\Python\Data\Samples')
False
Для установления факта существования файла служит path.isfile():
>>> os.path.isfile(r'C:\Users\User\Python\matrix_challenge.py')
False
Для преобразования пути в нижний регистр и нормализации слэшей используют path.normcase():
>>> os.path.normcase('C:/Users/User/Python')
'c:\\users\\user\\python'
Хотя путь к файлу (директории) представляет собой строку, создавать полный путь с помощью конкатенации считается моветоном – нужно использовать метод os.path.join():
# Неправильно:
my_cwd = os.getcwd()
file_name = 'my_solution.py'
path = my_cwd + '\\' + file_name
# Правильно:
path = os.path.join(my_cwd, file_name)
Результат:
C:\Users\User\Python\my_solution.py
Операции с каталогами и файлами в Python
Для создания новых директорий служит os.mkdir(); в метод нужно передать полный путь, включающий название нового каталога:
import os
my_cwd = os.getcwd()
new_dir = 'Solutions'
path = os.path.join(my_cwd, new_dir)
os.mkdir(path)
print(os.listdir())
Результат:
['Data', 'lambda_functions.py', 'letters.py', 'os_methods.py', 'passw_generator.py', 'points.py', 'population.py', 'Solutions']
Изменить рабочую директорию можно с помощью метода os.chdir(), это аналог CLI команды cd
:
>>> import os
>>> os.getcwd()
'C:\\Users\\User\\Python'
>>> os.chdir(r'C:\Users\User\Python\Data')
>>> os.getcwd()
'C:\\Users\\User\\Python\\Data'
Использование os.chdir() может привести к ошибке, если путь к переданной в метод директории указан неправильно или не существует. Поэтому этот метод стоит использовать только с обработкой ошибок:
import sys, os
my_cwd = os.getcwd()
new_cwd = r'C:\Users\User\Python\MyData'
try:
os.chdir(new_cwd)
print(f'Изменяем рабочую директорию на {os.getcwd()}')
except:
print(f'Произошла ошибка {sys.exc_info()}')
finally:
print('Восстанавливаем рабочую директорию на прежнюю')
os.chdir(my_cwd)
print(f'Текущая рабочая директория - {os.getcwd()}')
Вывод:
Произошла ошибка (<class 'FileNotFoundError'>, FileNotFoundError(2, 'Не удается найти указанный файл'), <traceback object at 0x024E9828>)
Восстанавливаем рабочую директорию на прежнюю
Текущая рабочая директория - C:\Users\User\Python
Создание директорий в Python
Для создания новых каталогов используют два метода:
- os.mkdir() – аналог CLI команды
mkdir
; создает новую папку по указанному пути, при условии, что все указанные промежуточные (вложенные) директории уже существуют. - os.makedirs() – аналог CLI команды
mkdir -p dir1\dir2
; помимо создания целевой папки, создает все промежуточные директории, если они не существуют.
Пример использования os.mkdir():
import os
new_dir = 'NewProjects'
parent_dir = r 'C:\Users\User\Python'
path = os.path.join(parent_dir, new_dir)
os.mkdir(path)
print(f'Директория {new_dir} создана: {os.listdir()}')
Результат:
Директория NewProjects создана: ['Data', 'lambda_functions.py', 'letters.py', 'NewProjects', 'os_methods.py', 'Other', 'passw_generator.py', 'points.py', 'population.py', 'Solutions']
Пример использования makedirs():
import os
new_dir = 'Django'
parent_dir = r'C:\Users\User\Python\Other\Projects\Modules'
path = os.path.join(parent_dir, new_dir)
os.makedirs(path)
print(f'Директория {new_dir} создана по адресу {os.path.dirname(path)}')
Результат:
Директория Django создана по адресу C:\Users\User\Python\Other\Projects\Modules
Копирование файлов и директорий в Python
Для копирования файлов используют метод shutil.copy2(), который принимает два аргумента – источник файла и директорию, в которую нужно скопировать файл:
import os
import shutil
dest_path = r'C:\Users\User\Python\Data'
source_path = r'C:\Users\User\lambda_exp.txt'
print(f'Файлы в директории {os.path.basename(dest_path)} до копирования файла \
{os.path.basename(source_path)}: {os.listdir(dest_path)}\n')
copy_file = shutil.copy2(source_path, dest_path)
print(f'Файлы в директории {os.path.basename(dest_path)} после копирования файла \
{os.path.basename(source_path)}: {os.listdir(dest_path)}')
Вывод:
Файлы в директории Data до копирования файла lambda_exp.txt: ['books_to_process.txt', 'challenge_data.txt', 'ledger.txt']
Файлы в директории Data после копирования файла lambda_exp.txt: ['books_to_process.txt', 'challenge_data.txt', 'lambda_exp.txt', 'ledger.txt']
Помимо метода shutil.copy2(), для копирования файлов можно пользоваться методом shutil.copy(). Разница между этими двумя методами в том, что в отличие от shutil.copy2(), метод shutil.copy() копирует только содержимое файла, но не метаданные:
import os
import shutil
dest_path = r'C:\Users\User\Python\Data'
source_path = r'C:\Users\User\logfile.txt'
print(f'Файлы в директории {os.path.basename(dest_path)} до копирования файла \
{os.path.basename(source_path)}: {os.listdir(dest_path)}\n')
print(f'Метаданные: {os.stat(source_path)}\n')
copy_file = shutil.copy(source_path, dest_path)
print(f'Файлы в директории {os.path.basename(dest_path)} после копирования файла \
{os.path.basename(source_path)}: {os.listdir(dest_path)}\n')
print(f'Метаданные: {os.stat(dest_path)}\n')
Вывод:
Файлы в директории Data до копирования файла logfile.txt: ['books_to_process.txt', 'challenge_data.txt', 'lambda_exp.txt']
Метаданные: os.stat_result(st_mode=33206, st_ino=18014398509552989, st_dev=4236505663, st_nlink=1, st_uid=0, st_gid=0, st_size=455, st_atime=1629682315, st_mtime=1629681887, st_ctime=1629682315)
Файлы в директории Data после копирования файла logfile.txt: ['books_to_process.txt', 'challenge_data.txt', 'lambda_exp.txt', 'logfile.txt']
Метаданные: os.stat_result(st_mode=16895, st_ino=11821949021901021, st_dev=4236505663, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1675257729, st_mtime=1675257729, st_ctime=1675084801)
Все содержимое каталога сразу можно скопировать с помощью shutil.copytree():
import os
import shutil
dest_path = r'C:\Users\User\Python\Other\Files'
source_path = r'C:\Users\User\Python\Other\Scripts'
print(f'Содержимое директории {os.path.basename(dest_path)} до копирования каталога \
{os.path.basename(source_path)}: {os.listdir(dest_path)}\n')
copy_dir = shutil.copytree(source_path, dest_path, dirs_exist_ok=True)
print(f'Содержимое директории {os.path.basename(dest_path)} после копирования \
{os.path.basename(source_path)}: {os.listdir(dest_path)}\n')
Вывод:
Содержимое директории Files до копирования каталога Scripts: []
Содержимое директории Files после копирования Scripts: ['progression.py', 'sitemap_generator.py']
Перемещение файлов и директорий
Для перемещения файлов используют метод shutil.move():
import os
import shutil
dest_path = r'C:\Users\User\Python\Other\Scripts'
source_path = r'C:\Users\User\Desktop\sitemap_generator.py'
print(f'Содержимое директории {os.path.basename(dest_path)} до копирования каталога \
{os.path.basename(source_path)}: {os.listdir(dest_path)}\n')
copy_dir = shutil.move(source_path, dest_path)
print(f'Содержимое директории {os.path.basename(dest_path)} после копирования \
{os.path.basename(source_path)}: {os.listdir(dest_path)}\n')
Вывод:
Содержимое директории Scripts до копирования каталога sitemap_generator.py: ['progression.py', 'wiki_scraping.py']
Содержимое директории Scripts после копирования sitemap_generator.py: ['progression.py', 'sitemap_generator.py', 'wiki_scraping.py']
Для перемещения содержимого всей директории в качестве функции указывают shutil.copytree():
copy_dir = shutil.move(source_path, dest_path, copy_function = shutil.copytree)
Удаление файлов и директорий
Для удаления директории вместе со всеми файлами используют shutil.rmtree():
import os
import shutil
dir_path = r'C:\Users\User\Python\Other'
remove_dir = 'Files'
path = os.path.join(dir_path, remove_dir)
print(f'Содержимое директории {os.path.basename(dir_path)} до удаления каталога \
{remove_dir}: {os.listdir(dir_path)}\n')
shutil.rmtree(path)
print(f'Содержимое директории {os.path.basename(dir_path)} после удаления \
{remove_dir}: {os.listdir(dir_path)}\n')
Вывод:
Содержимое директории Other до удаления каталога Files: ['Files', 'Projects']
Содержимое директории Other после удаления Files: ['Projects']
Другой метод для удаления пустых директорий – os.rmdir():
import os
import shutil
dir_path = r'C:\Users\User\Python\Other'
remove_dir = 'Scripts'
path = os.path.join(dir_path, remove_dir)
print(f'Содержимое директории {os.path.basename(dir_path)} до удаления каталога \
{remove_dir}: {os.listdir(dir_path)}\n')
os.rmdir(path)
print(f'Содержимое директории {os.path.basename(dir_path)} после удаления \
{remove_dir}: {os.listdir(dir_path)}\n')
Вывод:
Содержимое директории Other до удаления каталога Scripts: ['Projects', 'Scripts']
Содержимое директории Other после удаления Scripts: ['Projects']
Очевидный минус метода os.rmdir() в том, что он работает только на пустых директориях – если поместить в каталог Scripts хотя бы один файл, удалить его с os.rmdir() уже не получится:
Traceback (most recent call last):
File "C:\Users\User\Python\os_methods.py", line 8, in <module>
os.rmdir(path)
OSError: [WinError 145] Папка не пуста: 'C:\\Users\\User\\Python\\Other\\Scripts'
Для удаления файлов используют метод os.remove():
import os
import shutil
dir_path = r'C:\Users\User\Python\Other\Scripts'
remove_file = 'tetris_game.py'
path = os.path.join(dir_path, remove_file)
print(f'Содержимое директории {os.path.basename(dir_path)} до удаления файла \
{remove_file}: {os.listdir(dir_path)}\n')
os.remove(path)
print(f'Содержимое директории {os.path.basename(dir_path)} после удаления \
{remove_file}: {os.listdir(dir_path)}\n')
Вывод:
Содержимое директории Scripts до удаления файла tetris_game.py: ['tetris_game.py']
Содержимое директории Scripts после удаления tetris_game.py: []
Отлично! Вы научились управлять файлами и директориями с помощью Python.
Теперь вы можете писать скрипты для создания, копирования, перемещения и удаления папок и файлов. Это мощный навык для автоматизации рутинных задач.
Но что насчет содержимого этих файлов? Настоящая работа с данными начинается, когда мы заглядываем внутрь. В полной версии урока вы освоите:
- Безопасное открытие файлов с помощью
with open()
— золотой стандарт в Python. - Все режимы доступа (
'r'
,'w'
,'a'
) для чтения, полной перезаписи или дозаписи в конец файла. - Полный набор методов для чтения и записи данных: read, readline, write и другие.
- 10 практических задач по обработке текстовых файлов, от парсинга логов до анализа данных.
Комментарии