Наталья Кайда 06 февраля 2023

🐍 Самоучитель по Python для начинающих. Часть 15: Методы работы с файлами и файловой системой

Научимся создавать, переносить и удалять файлы и директории, а в конце статьи – решим 10 практических задач, связанных с чтением информации и с записью данных в текстовые файлы.
🐍 Самоучитель по Python для начинающих. Часть 15: Методы работы с файлами и файловой системой

Путь к файлам в 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'

    
🐍 Библиотека питониста
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста»
🐍🎓 Библиотека собеса по Python
Подтянуть свои знания по Python вы можете на нашем телеграм-канале «Библиотека собеса по Python»
🐍🧩 Библиотека задач по Python
Интересные задачи по Python для практики можно найти на нашем телеграм-канале «Библиотека задач по Python»

Получение информации о файлах и директориях

Метод 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 для новичков: бессрочный доступ к знаниям и поддержка экспертов
Онлайн-курс «Основы программирования на Python» от Proglib academy предлагает 32 практических урока с персональной обратной связью от экспертов, где вы создадите 4 реальных проекта для портфолио и получите все необходимые навыки для старта карьеры в IT.

Создание директорий в 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 практических задач по обработке текстовых файлов, от парсинга логов до анализа данных.

Комментарии

 
 

ВАКАНСИИ

Добавить вакансию

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

LIVE >

Подпишись

на push-уведомления