В Python есть несколько встроенных модулей и функций для работы с файлами. Эти функции распределены по нескольким модулям, таким как os, os.path, shutil и pathlib, и это всего лишь некоторые из них. В этом уроке собраны в одном месте многие функции, которые вам необходимо знать для выполнения наиболее распространенных операций с файлами в Python.

В этом уроке вы узнаете, как:

  • Получить свойства файла.
  • Создать каталоги.
  • Соответствие шаблонам в именах файлов.
  • Просматривать деревья каталогов.
  • Создавайте временные файлы и каталоги.
  • Удалить файлы и каталоги.
  • Копировать, перемещать или переименовывать файлы и каталоги.
  • Создание и извлечение архивов ZIP и TAR.
  • Открытие нескольких файлов с помощью модуля fileinput.

Содержание

Шаблон Python «with open(…) as …»   

Чтение и запись данных в файлы с помощью Python довольно просты. Для этого необходимо сначала открыть файлы в соответствующем режиме. Вот пример того, как использовать шаблон Python «with open (…) as…» для открытия текстового файла и чтения его содержимого:

with open('data.txt', 'r') as f:
    data = f.read()

open() принимает в качестве аргументов имя файла и режим. r открывает файл в режиме только для чтения. Чтобы записать данные в файл, вместо этого передайте w в качестве аргумента:

with open('data.txt', 'w') as f:
    data = 'some data to be written to the file'
    f.write(data)

В приведенных выше примерах open() открывает файлы для чтения или записи и возвращает дескриптор файла (в данном случае f), который предоставляет методы, которые можно использовать для чтения или записи данных в файл. Ознакомьтесь с разделами Чтение и запись файлов в Python и Working With File I/O in Python для получения дополнительной информации о том, как читать и записывать файлы.

Получение списка каталогов   

Предположим, в вашем текущем рабочем каталоге есть подкаталог my_directory со следующим содержимым:

my_directory/
|
├── sub_dir/
|   ├── bar.py
|   └── foo.py
|
├── sub_dir_b/
|   └── file4.txt
|
├── sub_dir_c/
|   ├── config.py
|   └── file5.txt
|
├── file1.py
├── file2.csv
└── file3.txt

Встроенный модуль os имеет ряд полезных функций, которые можно использовать для вывода списка содержимого каталогов и фильтрации результатов. Чтобы получить список всех файлов и папок в определенном каталоге файловой системы, используйте os.listdir() в устаревших версиях Python или os.scandir() в Python 3.x. os.scandir() — предпочтительный метод для использования, если вы также хотите получить свойства файла и каталога, такие как размер файла и дату модификации.

Список каталогов в устаревших версиях Python   

В версиях Python до Python 3 для получения списка каталого используетсяв метод os.listdir():

>>> import os
>>> entries = os.listdir('my_directory/')

os.listdir() возвращает список Python, содержащий имена файлов и подкаталогов в каталоге, заданном аргументом пути:

>>> os.listdir('my_directory/')
['sub_dir_c', 'file1.py', 'sub_dir_b', 'file3.txt', 'file2.csv', 'sub_dir']

Такой список каталогов нелегко прочитать. Распечатка вывода вызова os.listdir() с использованием цикла помогает очистить ситуацию:

>>> entries = os.listdir('my_directory/')
>>> for entry in entries:
...     print(entry)
...
...
sub_dir_c
file1.py
sub_dir_b
file3.txt
file2.csv
sub_dir

Список каталогов в современных версиях Python   

В современных версиях Python альтернативой os.listdir() является использование os.scandir() и pathlib.Path().

os.scandir() был представлен в Python 3.5 и задокументирован в PEP 471. os.scandir() возвращает итератор, а не список при вызове:

>>> import os
>>> entries = os.scandir('my_directory/')
>>> entries

ScandirIterator указывает на все записи в текущем каталоге. Вы можете перебрать содержимое итератора и распечатать имена файлов:

import os

with os.scandir('my_directory/') as entries:
    for entry in entries:
        print(entry.name)

Здесь os.scandir() используется вместе с оператором with, поскольку он поддерживает протокол диспетчера контекста. Использование диспетчера контекста закрывает итератор и автоматически освобождает полученные ресурсы после того, как итератор исчерпан. Результатом является распечатка имен файлов в my_directory/, как вы видели в операционной os.listdir() пример:

sub_dir_c
file1.py
sub_dir_b
file3.txt
file2.csv
sub_dir

Другой способ получить список каталогов — использовать модуль pathlib:

from pathlib import Path

entries = Path('my_directory/')
for entry in entries.iterdir():
    print(entry.name)

Объекты, возвращаемые Path, являются объектами PosixPath или WindowsPath в зависимости от ОС.

Объекты pathlib.Path() имеют метод .iterdir() для создания итератора всех файлов и папок в каталоге. Каждая запись, полученная с помощью .iterdir(), содержит информацию о файле или каталоге, такую ​​как его имя и атрибуты файла. pathlib был впервые представлен в Python 3.4 и является отличным дополнением к Python, предоставляющим объектно-ориентированный интерфейс для файловой системы.

В приведенном выше примере вы вызываете pathlib.Path() и передаете ему аргумент пути. Далее следует вызов .iterdir() для получения списка всех файлов и каталогов в my_directory. pathlib предлагает набор классов, отображающих большинство общих операций с путями простым и объектно-ориентированным способом. Использование pathlib более, если не так эффективно, как использование функций в os. Еще одно преимущество использования pathlib по сравнению с os заключается в том, что он уменьшает количество операций импорта, которые необходимо выполнить для управления путями файловой системы. Для дополнительной информации, прочтите модуль pathlib Python 3: Укрощение файловой системы.

Выполнение приведенного выше кода приводит к следующему:

sub_dir_c
file1.py
sub_dir_b
file3.txt
file2.csv
sub_dir

Использование pathlib.Path() или os.scandir() вместо os.listdir() является предпочтительным способом получения списка каталогов, особенно когда вы работаете с кодом, которому требуется информация о типе файла и атрибутах файла. pathlib.Path() предлагает большую часть функций обработки файлов и путей, которые есть в os и shutil, и его методы более эффективны, чем некоторые из этих модулей. Вскоре мы обсудим, как получить свойства файла.

Вот еще раз функции листинга каталогов:

Функция Описание
os.listdir() Возвращает список всех файлов и папок в каталоге
os.scandir() Возвращает итератор всех объектов в каталоге, включая информацию об атрибутах файла
pathlib.Path.iterdir() Возвращает итератор всех объектов в каталоге, включая информацию об атрибутах файла

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

Список всех файлов в каталоге   

В этом разделе показано, как распечатать имена файлов в каталоге с помощью os.listdir(), os.scandir() и pathlib.Path(). Чтобы отфильтровать каталоги и перечислить только файлы из списка каталогов, созданного os.listdir(), используйте os.path:

import os

# Список всех файлов в каталоге с помощью os.listdir
basepath = 'my_directory/'
for entry in os.listdir(basepath):
    if os.path.isfile(os.path.join(basepath, entry)):
        print(entry)

Здесь вызов os.listdir() возвращает список всего по указанному пути, а затем этот список фильтруется с помощью os.path.isfile(), чтобы распечатать только файлы, а не каталоги. Это дает следующий результат:

file1.py
file3.txt
file2.csv

Более простой способ перечислить файлы в каталоге — использовать os.scandir() или pathlib.Path():

import os

# List all files in a directory using scandir()
basepath = 'my_directory/'
with os.scandir(basepath) as entries:
    for entry in entries:
        if entry.is_file():
            print(entry.name)

Преимущество использования os.scandir() состоит в том, что он выглядит чище и проще для понимания, чем использование os.listdir(), хотя это на одну строку кода длиннее. Вызов entry.is_file() для каждого элемента в ScandirIterator возвращает True, если объект является файлом. Распечатав имена всех файлов в каталоге, вы получите следующий результат:

file1.py
file3.txt
file2.csv

Вот как вывести список файлов в каталоге с помощью pathlib.Path():

from pathlib import Path

basepath = Path('my_directory/')
files_in_basepath = basepath.iterdir()
for item in files_in_basepath:
    if item.is_file():
        print(item.name)

Здесь вы вызываете .is_file() для каждой записи, полученной с помощью .iterdir(). Результат такой же:

file1.py
file3.txt
file2.csv

Приведенный выше код можно сделать более кратким, если объединить цикл for и оператор if в одно выражение генератора.

Модифицированная версия выглядит так:

from pathlib import Path

# Вывести список всех файлов в каталоге, используя pathlib
basepath = Path('my_directory/')
files_in_basepath = (entry for entry in basepath.iterdir() if entry.is_file())
for item in files_in_basepath:
    print(item.name)

Это дает точно такой же результат, как и в предыдущем примере. В этом разделе показано, что фильтрация файлов или каталогов с использованием os.scandir() и pathlib.Path() кажется более интуитивно понятной и выглядит более чистой, чем использование os.listdir() в сочетании с os.path.

Список подкаталогов   

Чтобы вывести список подкаталогов вместо файлов, используйте один из следующих способов. Вот как использовать os.listdir() и os.path():

import os

# Список всех подкаталогов с помощью os.listdir
basepath = 'my_directory/'
for entry in os.listdir(basepath):
    if os.path.isdir(os.path.join(basepath, entry)):
        print(entry)

Такое управление путями файловой системы может быстро стать обременительным, если у вас есть несколько вызовов os.path.join(). Запуск этого на моем компьютере дает следующий результат:

sub_dir_c
sub_dir_b
sub_dir

Вот как использовать os.scandir():

import os

# Вывести список всех подкаталогов с помощью scandir()
basepath = 'my_directory/'
with os.scandir(basepath) as entries:
    for entry in entries:
        if entry.is_dir():
            print(entry.name)

Как и в примере со списком файлов, здесь вы вызываете .is_dir() для каждой записи, возвращаемой os.scandir(). Если запись является каталогом, .is_dir() возвращает True, и имя каталога распечатывается. Результат такой же, как и выше:

sub_dir_c
sub_dir_b
sub_dir

Вот как использовать pathlib.Path():

from pathlib import Path

# Список всех подкаталогов с помощью pathlib
basepath = Path('my_directory/')
for entry in basepath.iterdir():
    if entry.is_dir():
        print(entry.name)

Вызов .is_dir() для каждой записи итератора базового пути проверяет, является ли запись файлом или каталогом. Если запись является каталогом, ее имя выводится на экран, а результат такой же, как и в предыдущем примере:

sub_dir_c
sub_dir_b
sub_dir

Получение атрибутов файла   

Python упрощает получение атрибутов файла, таких как размер файла и время изменения. Это делается с помощью os.stat(), os.scandir() или pathlib.Path().

os.scandir() и pathlib.Path() получают список каталогов с объединенными атрибутами файлов. Это может быть потенциально более эффективным, чем использование os.listdir() для вывода списка файлов и последующего получения информации об атрибутах для каждого файла.

В приведенных ниже примерах показано, как получить время последнего изменения файлов в my_directory/. Вывод в секундах:

>>> import os
>>> with os.scandir('my_directory/') as dir_contents:
...     for entry in dir_contents:
...         info = entry.stat()
...         print(info.st_mtime)
...
1539032199.0052035
1539032469.6324475
1538998552.2402923
1540233322.4009316
1537192240.0497339
1540266380.3434134

os.scandir() возвращает объект ScandirIterator. Каждая запись в объекте ScandirIterator имеет метод .stat(), который извлекает информацию о файле или каталоге, на которые он указывает. .stat() предоставляет такую ​​информацию, как размер файла и время последней модификации. В приведенном выше примере код выводит атрибут st_mtime, время последнего изменения содержимого файла.

В модуле pathlib есть соответствующие методы для получения информации о файлах, которые дают те же результаты:

>>> from pathlib import Path
>>> current_dir = Path('my_directory')
>>> for path in current_dir.iterdir():
...     info = path.stat()
...     print(info.st_mtime)
...
1539032199.0052035
1539032469.6324475
1538998552.2402923
1540233322.4009316
1537192240.0497339
1540266380.3434134

В приведенном выше примере код проходит через объект, возвращаемый .iterdir(), и извлекает атрибуты файла с помощью вызова .stat() для каждого файла в списке каталогов. Атрибут st_mtime возвращает значение с плавающей запятой, которое представляет секунды с начала эпохи. Чтобы преобразовать значения, возвращаемые st_mtime для отображения, можно написать вспомогательную функцию для преобразования секунд в объект datetime:

from datetime import datetime
from os import scandir

def convert_date(timestamp):
    d = datetime.utcfromtimestamp(timestamp)
    formated_date = d.strftime('%d %b %Y')
    return formated_date

def get_files():
    dir_entries = scandir('my_directory/')
    for entry in dir_entries:
        if entry.is_file():
            info = entry.stat()
            print(f'{entry.name}\t Last Modified: {convert_date(info.st_mtime)}')

Сначала получаем список файлов в my_directory и их атрибуты, а затем вызовет convert_date() для преобразования времени последнего изменения каждого файла в удобочитаемую форму. convert_date() использует .strftime() для преобразования времени в секундах в строку.

В .strftime() передаются следующие аргументы:

  • %d — день месяца
  • %b — месяц в сокращенной форме
  • %Y — год

Вместе эти директивы производят вывод, который выглядит следующим образом:

>>> get_files()
file1.py        Last modified:  04 Oct 2018
file3.txt       Last modified:  17 Sep 2018
file2.txt       Last modified:  17 Sep 2018

Синтаксис преобразования даты и времени в строки может сбивать с толку. Чтобы узнать больше об этом, ознакомьтесь с официальной документацией по нему. Еще одна удобная ссылка, которую легко запомнить, — это http://strftime.org/.

Создание каталогов   

Рано или поздно программы, которые вы пишете, должны будут создавать каталоги, чтобы хранить в них данные. os и pathlib включают функции для создания каталогов. Мы рассмотрим это:

Функция Описание
os.mkdir() Создает единственный подкаталог
pathlib.Path.mkdir() Создает один или несколько каталогов
os.makedirs() Создает несколько каталогов, включая промежуточные каталоги

Создание единого каталога   

Чтобы создать единый каталог, передайте путь к каталогу в качестве параметра функции os.mkdir():

import os

os.mkdir('example_directory/')

Если каталог уже существует, os.mkdir() вызывает FileExistsError. В качестве альтернативы вы можете создать каталог с помощью pathlib:

from pathlib import Path

p = Path('example_directory/')
p.mkdir()

Если путь уже существует, mkdir() вызывает FileExistsError:

>>> p.mkdir()
Traceback (most recent call last):
  File '', line 1, in 
  File '/usr/lib/python3.5/pathlib.py', line 1214, in mkdir
    self._accessor.mkdir(self, mode)
  File '/usr/lib/python3.5/pathlib.py', line 371, in wrapped
    return strfunc(str(pathobj), *args)
FileExistsError: [Errno 17] File exists: '.'
[Errno 17] File exists: '.'

Чтобы избежать подобных ошибок, перехватывайте ошибку, когда она возникает, и дайте знать своему пользователю:

from pathlib import Path

p = Path('example_directory')
try:
    p.mkdir()
except FileExistsError as exc:
    print(exc)

В качестве альтернативы вы можете игнорировать FileExistsError, передав аргумент exist_ok = True в .mkdir():

from pathlib import Path

p = Path('example_directory')
p.mkdir(exist_ok=True)

Это не вызовет ошибки, если каталог уже существует.

Создание нескольких каталогов   

os.makedirs() похож на os.mkdir(). Разница между ними в том, что os.makedirs() может не только создавать отдельные каталоги, но также может использоваться для создания деревьев каталогов. Другими словами, он может создавать любые необходимые промежуточные папки, чтобы гарантировать существование полного пути.

os.makedirs() аналогичен запуску mkdir -p в Bash. Например, чтобы создать группу каталогов типа 2018/10/05, все, что вам нужно сделать, это следующее:

import os


os.makedirs('2018/10/05')

В результате получите вложенную структуру каталогов, содержащую папки 2018, 10 и 05:

.
|
└── 2018/
    └── 10/
        └── 05/

.makedirs() создает каталоги с разрешениями по умолчанию. Если вам нужно создать каталоги с разными разрешениями, вызовите .makedirs() и перейдите в режим, в котором вы хотите, чтобы каталоги были созданы:

import os

os.makedirs('2018/10/05', mode=0o770)

Это создает структуру каталогов 2018/10/05 и дает владельцу и пользователям группы права на чтение, запись и выполнение. Режим по умолчанию — 0o777, и биты прав доступа к файлам существующих родительских каталогов не изменяются. Дополнительные сведения о правах доступа к файлам и о том, как применяется режим, см. в документации. Запустите tree, чтобы убедиться, что были применены правильные разрешения:

$ tree -p -i .
.
[drwxrwx---]  2018
[drwxrwx---]  10
[drwxrwx---]  05

Здесь распечатано дерево каталогов текущего каталога. tree обычно используется для отображения содержимого каталогов в древовидном формате. Передав ему аргументы -p и -i, вы распечатаете имена каталогов и информацию о правах доступа к файлам в вертикальном списке. -p распечатывает права доступа к файлам и -i заставляет дерево создавать вертикальный список без строк отступов.

Как видите, все каталоги имеют права доступа 770. Альтернативный способ создания каталогов — использовать .mkdir() из pathlib.Path:

import pathlib

p = pathlib.Path('2018/10/05')
p.mkdir(parents=True)

Передача parent = True в Path.mkdir() заставляет его создавать каталог 05 и все родительские каталоги, необходимые для того, чтобы путь был действительным.

По умолчанию os.makedirs() и Path.mkdir() вызывают ошибку OSError, если каталог уже существует. Это поведение можно переопределить (начиная с Python 3.2) передавая exist_ok = True в качестве аргумента ключевого слова при вызове каждой функции.

Выполнение приведенного выше кода создает структуру каталогов, подобную приведенной ниже, за один раз:

.
|
└── 2018/
    └── 10/
        └── 05/

Я предпочитаю использовать pathlib при создании каталогов, так как можно использовать ту же функцию для создания одиночных или вложенных каталогов.

Сопоставление имени файла с шаблоном   

Использование строковых методов   

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

Вам доступны следующие методы и функции:

  • endwith() и startwith() строковые методы
  • fnmatch.fnmatch()
  • glob.glob()
  • pathlib.Path.glob()

Каждый из них обсуждается ниже. Примеры в этом разделе будут выполняться в каталоге с именем some_directory, который имеет следующую структуру:

.
|
├── sub_dir/
|   ├── file1.py
|   └── file2.py
|
├── admin.py
├── data_01_backup.txt
├── data_01.txt
├── data_02_backup.txt
├── data_02.txt
├── data_03_backup.txt
├── data_03.txt
└── tests.py

Если вы используете оболочку Bash, вы можете создать указанную выше структуру каталогов с помощью следующих команд:

$ mkdir some_directory
$ cd some_directory/
$ mkdir sub_dir
$ touch sub_dir/file1.py sub_dir/file2.py
$ touch data_{01..03}.txt data_{01..03}_backup.txt admin.py tests.py

Это создаст каталог some_directory/, перейдет в него, а затем создаст sub_dir. Следующая строка создает файлы file1.py и file2.py в sub_dir, а последняя строка создает все остальные файлы с использованием расширения. Чтобы узнать больше о расширении оболочки, посетите этот сайт.

Использование строковых методов   

Python имеет несколько встроенных методов для изменения и управления строками. Два из этих методов, .startswith() и .endswith(), полезны при поиске шаблонов в именах файлов. Для этого сначала получите список каталогов, а затем переберите его:

>>> import os

>>> # Получить файлы .txt
>>> for f_name in os.listdir('some_directory'):
...     if f_name.endswith('.txt'):
...         print(f_name)

Приведенный выше код находит все файлы в some_directory/, выполняет итерацию по ним и использует .endswith() для распечатки имен файлов с расширением .txt. Запуск этого на моем компьютере дает следующий результат:

data_01.txt
data_03.txt
data_03_backup.txt
data_02_backup.txt
data_02.txt
data_01_backup.txt

Простое сопоставление с шаблоном имени файла с помощью fnmatch   

Возможности сопоставления строковых методов ограничены. fnmatch имеет более продвинутые функции и методы для сопоставления с образцом. Мы рассмотрим fnmatch.fnmatch(), функцию, которая поддерживает использование подстановочных знаков, таких как * и ? чтобы соответствовать именам файлов. Например, чтобы найти все файлы .txt в каталоге с помощью fnmatch, вы должны сделать следующее:

>>> import os
>>> import fnmatch

>>> for file_name in os.listdir('some_directory/'):
...     if fnmatch.fnmatch(file_name, '*.txt'):
...         print(file_name)

Здесь выполняются итерацию по списку файлов в some_directory и использует .fnmatch() для поиска файлов с расширением .txt по шаблону.

Более расширенное сопоставление с шаблоном   

Предположим, вы хотите найти файлы .txt, соответствующие определенным критериям. Например, вас может интересовать только поиск файлов .txt, содержащих слово data, число между набором подчеркиваний и слово backup в их имени файла. Что-то похожее на data_01_backup, data_02_backup или data_03_backup.

Используя fnmatch.fnmatch(), можно сделать так:

>>> for filename in os.listdir('.'):
...     if fnmatch.fnmatch(filename, 'data_*_backup.txt'):
...         print(filename)

Здесь вы печатаете только имена файлов, которые соответствуют шаблону data _ * _ backup.txt. Звездочка в шаблоне будет соответствовать любому символу, поэтому при его запуске будут найдены все текстовые файлы, имена файлов которых начинаются со слова data и заканчиваются на backup.txt, как вы можете видеть из вывода ниже:

data_03_backup.txt
data_02_backup.txt
data_01_backup.txt

Сопоставление с шаблоном имени файла с помощью glob   

Еще один полезный модуль для сопоставления с образцом — glob.

.glob() в модуле glob работает так же, как fnmatch.fnmatch(), но в отличие от fnmatch.fnmatch(), он обрабатывает файлы, начинающиеся с точки (.), как особые.

UNIX и родственные системы переводят шаблоны имен с помощью подстановочных знаков, например, ? и * в список файлов. Это называется глобусом.

Например, ввод mv *.py python_files/ в оболочке UNIX перемещает (mv) все файлы с расширением .py из текущего каталога в каталог python_files. Символ * — это подстановочный знак, означающий «любое количество символов», а *.py — шаблон glob. Эта возможность оболочки недоступна в операционной системе Windows. Модуль glob добавляет эту возможность в Python, что позволяет программам Windows использовать эту функцию.

Вот пример того, как использовать glob для поиска всех исходных файлов Python (.py) в текущем каталоге:

>>> import glob
>>> glob.glob('*.py')
['admin.py', 'tests.py']

glob.glob ('*. py') ищет все файлы с расширением .py в текущем каталоге и возвращает их в виде списка. glob также поддерживает подстановочные знаки в стиле оболочки для соответствия шаблонам:

>>> import glob
>>> for name in glob.glob('*[0-9]*.txt'):
...     print(name)

Это найдет все текстовые файлы (.txt), которые содержат цифры в имени файла:

data_01.txt
data_03.txt
data_03_backup.txt
data_02_backup.txt
data_02.txt
data_01_backup.txt

glob также упрощает рекурсивный поиск файлов в подкаталогах:

>>> import glob
>>> for file in glob.iglob('**/*.py', recursive=True):
...     print(file)

В этом примере используется glob.iglob() для поиска файлов .py в текущем каталоге и подкаталогах. Передача recursive=True в качестве аргумента для .iglob() заставляет его искать файлы .py в текущем каталоге и любых подкаталогах. Разница между glob.iglob() и glob.glob() заключается в том, что .iglob() возвращает итератор вместо списка.Выполнение указанной выше программы приводит к следующему:

admin.py
tests.py
sub_dir/file1.py
sub_dir/file2.py

pathlib содержит аналогичные методы для создания гибких списков файлов. В приведенном ниже примере показано, как вы можете использовать .Path.glob() для перечисления типов файлов, начинающихся с буквы p:

>>> from pathlib import Path
>>> p = Path('.')
>>> for name in p.glob('*.p*'):
...     print(name)

admin.py
scraper.py
docs.pdf

Вызов p.glob('*.P*') возвращает объект-генератор, который указывает на все файлы в текущем каталоге, которые начинаются с буквы p в их расширении.

Path.glob() похож на os.glob(), описанный выше. Как видите, pathlib объединяет многие из лучших функций модулей os, os.path и glob в один модуль,что делает его использование приятным.

Напомним, вот таблица функций, которые мы рассмотрели в этом разделе:

Функция Описание
startswith() Проверяет, начинается ли строка с указанного шаблона и возвращаетTrueилиFalse
endswith() Проверяет, заканчивается ли строка указанным шаблоном и возвращаетTrueилиFalse
fnmatch.fnmatch(имя файла, шаблон) Проверяет, соответствует ли имя файла шаблону и возвращаетTrueилиFalse
glob.glob() Возвращает список имен файлов, соответствующих шаблону
pathlib.Path.glob() Находит шаблоны в именах путей и возвращает объект-генератор

Просмотр каталогов и обработка файлов   

Обычной задачей программирования является обход дерева каталогов и обработка файлов в дереве. Давайте посмотрим, как для этого можно использовать встроенную функцию Python os.walk(). os.walk() используется для генерации имени файла в дереве каталогов путем обхода дерева сверху вниз или снизу вверх. Для целей этого разделамы будем работать со следующим деревом каталогов:

.
|
├── folder_1/
|   ├── file1.py
|   ├── file2.py
|   └── file3.py
|
├── folder_2/
|   ├── file4.py
|   ├── file5.py
|   └── file6.py
|
├── test1.txt
└── test2.txt

Ниже приведен пример, показывающий, как вывести список всех файлов и каталогов в дереве каталогов с помощью os.walk().

os.walk() по умолчанию перемещается по каталогам сверху вниз:

# Обойти дерево каталогов и распечатать имена каталогов и файлов
for dirpath, dirnames, files in os.walk('.'):
    print(f'Found directory: {dirpath}')
    for file_name in files:
        print(file_name)

os.walk() возвращает три значения на каждой итерации цикла:

  1. Имя текущей папки
  2. Список папок в текущей папке
  3. Список файлов в текущей папке

На каждой итерации он распечатывает имена найденных подкаталогов и файлов:

Found directory: .
test1.txt
test2.txt
Found directory: ./folder_1
file1.py
file3.py
file2.py
Found directory: ./folder_2
file4.py
file5.py
file6.py

Чтобы пройти по дереву каталогов снизу вверх, передайте аргумент ключевого слова topdown = False в os.walk():

for dirpath, dirnames, files in os.walk('.', topdown=False):
    print(f'Found directory: {dirpath}')
    for file_name in files:
        print(file_name)

Передача аргумента topdown = False заставит os.walk() сначала распечатать файлы, которые она находит в подкаталогах:

Found directory: ./folder_1
file1.py
file3.py
file2.py
Found directory: ./folder_2
file4.py
file5.py
file6.py
Found directory: .
test1.txt
test2.txt

Как видите, программа запускается с перечисления содержимого подкаталогов перед выводом содержимого корневого каталога. Это очень полезно в ситуациях, когда вы хотите рекурсивно удалить файлы и каталоги. Вы узнаете, как это сделать, в следующих разделах. По умолчанию os.walk не переходит к символическим ссылкам, ведущим к каталогам. Это поведение можно изменить, вызвав его с аргументом followlinks = True.

Создание временных файлов и каталогов   

Python предоставляет удобный модуль для создания временных файлов и каталогов, называемый tempfile.

tempfile можно использовать для временного открытия и хранения данных в файле или каталоге во время работы вашей программы. tempfile обрабатывает удаление временных файлов, когда ваша программа завершает работу с ними.

Вот как создать временный файл:

from tempfile import TemporaryFile

# Создать временный файл и записать в него данные
fp = TemporaryFile('w+t')
fp.write('Hello universe!')

# Вернуться к началу и прочитать данные из файла
fp.seek(0)
data = fp.read()

# Закройте файл, после чего он будет удален
fp.close()

Первый шаг — импортировать TemporaryFile из модуля tempfile. Затем создайте объект, подобный файлу, с помощью метода TemporaryFile(), вызвав его и передав режим, в котором вы хотите открыть файл. Это создаст и откроет файл, который можно использовать в качестве области временного хранения.

В приведенном выше примере это режим 'w + t',что заставляет tempfile создавать временный текстовый файл в режиме записи. Нет необходимости давать временному файлу имя файла, поскольку он будет уничтожен после завершения выполнения сценария.

После записи в файл вы можете прочитать его и закрыть, когда закончите обработку. После закрытия файла он будет удален из файловой системы.Если вам нужно назвать временные файлы, созданные с помощью tempfile, используйте tempfile.NamedTemporaryFile().

Временные файлы и каталоги, созданные с помощью tempfile, хранятся в специальном системном каталоге для хранения временных файлов. Python ищет в стандартном списке каталогов тот, в котором пользователь может создавать файлы.

В Windows каталоги — C:\TEMP, C:\TMP, \TEMP и \TMP в указанном порядке. На всех других платформах это каталоги /tmp, /var/tmp и /usr/tmp в указанном порядке. В крайнем случае, tempfile сохранит временные файлы и каталоги в текущем каталоге.

.TemporaryFile() также является диспетчером контекста, поэтому его можно использовать вместе с оператором with. Использование диспетчера контекста автоматически закрывает и удаляет файл после того, как он был прочитан:

with TemporaryFile('w+t') as fp:
    fp.write('Hello universe!')
    fp.seek(0)
    fp.read()
# Файл закрыт и удален

Создаётся временный файл и считывает из него данные. Как только содержимое файла считывается, временный файл закрывается и удаляется из файловой системы.

tempfile также можно использовать для создания временных каталогов. Давайте посмотрим, как это можно сделать с помощью tempfile.TemporaryDirectory():

>>> import tempfile
>>> with tempfile.TemporaryDirectory() as tmpdir:
...     print('Created temporary directory ', tmpdir)
...     os.path.exists(tmpdir)
...
Created temporary directory  /tmp/tmpoxbkrm6c
True

>>># Содержимое каталога было удалено
...
>>> tmpdir
'/tmp/tmpoxbkrm6c'
>>> os.path.exists(tmpdir)
False

Вызов tempfile.TemporaryDirectory() создает временный каталог в файловой системе и возвращает объект, представляющий этот каталог. В приведенном выше примере каталог создается с помощью диспетчера контекста, а имя каталога хранится в tmpdir. Третья строка выводит имя временного каталога и os.path.exists (tmpdir) подтверждает, действительно ли каталог был создан в файловой системе.

После того, как диспетчер контекста выходит из контекста, временный каталог удаляется, а вызов os.path.exists (tmpdir) возвращает False, что означает, что каталог был успешно удален.

Удаление файлов и каталогов   

Вы можете удалять отдельные файлы, каталоги и целые деревья каталогов, используя методы, найденные в модулях os, shutil и pathlib. В следующих разделах описывается, как удалить файлы и каталоги, которые вам больше не нужны.

Удаление файлов в Python   

Чтобы удалить один файл, используйте pathlib.Path.unlink(), os.remove(). или os.unlink().

os.remove() и os.unlink() семантически идентичны. Чтобы удалить файл с помощью os.remove(), сделайте следующее:

import os

data_file = 'C:\\Users\\vuyisile\\Desktop\\Test\\data.txt'
os.remove(data_file)

Удаление файла с помощью os.unlink() аналогично тому, как вы это делаете с помощью os.remove():

import os

data_file = 'C:\\Users\\vuyisile\\Desktop\\Test\\data.txt'
os.unlink(data_file)

Вызов .unlink() или .remove() для файла удаляет файл из файловой системы. Эти две функции вызовут ошибку OSError, если переданный им путь указывает на каталог, а не на файл. Чтобы этого избежать, вы можете либо проверить, что вы пытаетесь удалить, на самом деле файл, и удалить его только в том случае, если это так,или вы можете использовать обработку исключений для обработки ошибки OSError:

import os

data_file = 'home/data.txt'

# Если файл существует, удалите его
if os.path.isfile(data_file):
    os.remove(data_file)
else:
    print(f'Ошибка: {data_file} неверное имя файла')

os.path.isfile() проверяет, действительно ли data_file является файлом. Если это так, он удаляется вызовом os.remove(). Если data_file указывает на папку, на консоль выводится сообщение об ошибке.

В следующем примере показано, как использовать обработку исключений для обработки ошибок при удалении файлов:

import os

data_file = 'home/data.txt'

# Use exception handling
try:
    os.remove(data_file)
except OSError as e:
    print(f'Ошибка: {data_file} : {e.strerror}')

Приведенный выше код пытается сначала удалить файл перед проверкой его типа. Если data_file на самом деле не является файлом, возникшая ошибка OSError обрабатывается в предложении except, и на консоль выводится сообщение об ошибке. Распечатываемое сообщение об ошибке отформатировано с использованием f-строк Python.

Наконец, можно использовать pathlib.Path.unlink() для удаления файлов:

from pathlib import Path

data_file = Path('home/data.txt')

try:
    data_file.unlink()
except IsADirectoryError as e:
    print(f'Ошибка: {data_file} : {e.strerror}')

Создаётся объект Path с именем data_file, который указывает на файл. Вызов .remove() для data_file удалит home/data.txt. Если data_file указывает на каталог, возникает IsADirectoryError. Стоит отметить, что указанная выше программа Python имеет те же разрешения, что и пользователь, запускающий ее. Если у пользователя нет разрешения на удаление файла, возникает ошибка PermissionError.

Удаление каталогов   

Стандартная библиотека предлагает следующие функции для удаления каталогов:

  • os.rmdir()
  • pathlib.Path.rmdir()
  • shutil.rmtree()

Чтобы удалить отдельный каталог или папку, используйте os.rmdir() или pathlib.rmdir(). Эти две функции работают, только если каталог, который вы пытаетесь удалить, пуст. Если каталог не пустой, возникает ошибка OSError. Вот как удалить папку:

import os

trash_dir = 'my_documents/bad_dir'

try:
    os.rmdir(trash_dir)
except OSError as e:
    print(f'Error: {trash_dir} : {e.strerror}')

Здесь каталог trash_dir удаляется путем передачи его пути в os.rmdir(). Если каталог не пустой, на экран выводится сообщение об ошибке:

Traceback (most recent call last):
  File '', line 1, in 
OSError: [Errno 39] Directory not empty: 'my_documents/bad_dir'

В качестве альтернативы вы можете использовать pathlib для удаления каталогов:

from pathlib import Path

trash_dir = Path('my_documents/bad_dir')

try:
    trash_dir.rmdir()
except OSError as e:
    print(f'Error: {trash_dir} : {e.strerror}')

Здесь вы создаётся объект Path, указывающий на удаляемый каталог. Вызов .rmdir() для объекта Path удалит его, если он пуст.

Удаление всех деревьев каталогов   

Чтобы удалить непустые каталоги и целые деревья каталогов, Python предлагает shutil.rmtree():

import shutil

trash_dir = 'my_documents/bad_dir'

try:
    shutil.rmtree(trash_dir)
except OSError as e:
    print(f'Error: {trash_dir} : {e.strerror}')

Все в trash_dir удаляется при вызове shutil.rmtree(). Могут быть случаи, когда вы захотите рекурсивно удалить пустые папки. Вы можете сделать это, используя один из методов, описанных выше вместе с os.walk():

import os

for dirpath, dirnames, files in os.walk('.', topdown=False):
    try:
        os.rmdir(dirpath)
    except OSError as ex:
        pass

Здесь просматривается дерево каталогов и делается попытка удалить каждый найденный каталог. Если каталог не пустой, возникает ошибка OSError и этот каталог пропускается. В таблице ниже перечислены функции, рассматриваемые в этом разделе:

Функция Описание
os.remove() Удаляет файл и не удаляет каталоги
os.unlink() Идентиченos.remove()и удаляет один файл
pathlib.Path.unlink() Удаляет файл и не может удалять каталоги
os.rmdir() Удаляет пустой каталог
pathlib.Path.rmdir() Удаляет пустой каталог
shutil.rmtree() Удаляет все дерево каталогов и может использоваться для удаления непустых каталогов

Копирование, перемещение и переименование файлов и каталогов   

Python поставляется с модулем shutil. shutil — это сокращение от short for shell utilities (служебных программ оболочки). Он обеспечивает ряд высокоуровневых операций с файлами для поддержки копирования, архивирования и удаления файлов и каталогов. В этом разделе вы узнаете, как перемещать и копировать файлы и каталоги.

Копирование файлов в Python   

shutil предлагает несколько функций для копирования файлов. Наиболее часто используемые функции — это shutil.copy() и shutil.copy2(). Чтобы скопировать файл из одного места в другое с помощью shutil.copy(), сделайте следующее:

import shutil

src = 'path/to/file.txt'
dst = 'path/to/dest_dir'
shutil.copy(src, dst)

shutil.copy() сравнима с командой cp в системах на основе UNIX. shutil.copy (src, dst) скопирует файл src в место, указанное в dst. Если dst является файлом, содержимое этого файла заменяется содержимым src. Если dst — это каталог, то src будет скопирован в этот каталог. shutil.copy() копирует только содержимое файла и разрешения файла. Другие метаданные, такие как время создания и изменения файла, не сохраняются.

Чтобы сохранить все метаданные файла при копировании, используйте shutil.copy2():

import shutil

src = 'path/to/file.txt'
dst = 'path/to/dest_dir'
shutil.copy2(src, dst)

Использование .copy2() сохраняет детали о файле, такие как время последнего доступа, биты прав доступа, время последнего изменения и флаги.

Копирование каталогов   

В то время как shutil.copy() копирует только один файл, shutil.copytree() копирует весь каталог и все, что в нем содержится. shutil.copytree (src, dest) принимает два аргумента: исходный каталог и целевой каталог, в который будут скопированы файлы и папки. Вот пример того, как скопировать содержимое одной папки в другое место:

>>> import shutil
>>> shutil.copytree('data_1', 'data1_backup')
'data1_backup'

В этом примере .copytree() копирует содержимое data_1 в новое место data1_backup и возвращает целевой каталог. Целевой каталог еще не должен существовать. Он будет создан вместе с отсутствующими родительскими каталогами. shutil.copytree() — хороший способ сделать резервную копию ваших файлов.

Перемещение файлов и каталогов   

Чтобы переместить файл или каталог в другое место, используйте shutil.move (src, dst).

src — это файл или каталог, который нужно переместить, а dst — это место назначения:

>>> import shutil
>>> shutil.move('dir_1/', 'backup/')
'backup'

shutil.move('dir_1/', 'backup/') перемещает dir_1/ в backup/, если backup/ существует. Если backup/ не существует, каталог dir_1/ будет переименован в backup.

Переименование файлов и каталогов   

В Python есть функция os.rename (src, dst) для переименования файлов и каталогов:

>>> os.rename('first.zip', 'first_01.zip')

В строке выше first.zip будет переименован в first_01.zip. Если целевой путь указывает на каталог, это вызовет ошибку OSError.

Другой способ переименовать файлы или каталоги — использовать rename() из модуля pathlib:

>>> from pathlib import Path
>>> data_file = Path('data_01.txt')
>>> data_file.rename('data.txt')

Чтобы переименовать файлы с помощью pathlib, вы сначала создаете объект pathlib.Path(), который содержит путь к файлу, который вы хотите заменить. Следующим шагом является вызов метода rename() для объекта пути и передача нового имени файла или каталога, который вы переименовываете.

Архивирование   

Архивы — это удобный способ упаковать несколько файлов в один. Двумя наиболее распространенными типами архивов являются ZIP и TAR. Написанные вами программы Python могут создавать, читать и извлекать данные из архивов. В этом разделе вы узнаете, как читать и писать в оба формата архивов.

Чтение ZIP-файлов   

Модуль zipfile — это модуль низкого уровня, который является частью стандартной библиотеки Python. zipfile имеет функции, которые позволяют легко открывать и извлекать файлы ZIP. Чтобы прочитать содержимое ZIP-файла, первое, что нужно сделать, — это создать объект ZipFile. Объекты ZipFile аналогичны файловым объектам, созданным с помощью open().ZipFile также является диспетчером контекста и поэтому поддерживает оператор with:

import zipfile

with zipfile.ZipFile('data.zip', 'r') as zipobj:

Здесь создаётся объект ZipFile, передавая имя ZIP-файла для открытия в режиме чтения. После открытия ZIP-файла информация об архиве может быть доступна с помощью функций, предоставляемых модулем zipfile. Архив data.zip в приведенном выше примере был создан из каталога с именем data, который содержит всего 5 файлов и 1 подкаталог:

.
|
├── sub_dir/
|   ├── bar.py
|   └── foo.py
|
├── file1.py
├── file2.py
└── file3.py

Чтобы получить список файлов в архиве, вызовите namelist() объекта ZipFile:

import zipfile

with zipfile.ZipFile('data.zip', 'r') as zipobj:
    zipobj.namelist()

Создаётся список:

['file1.py', 'file2.py', 'file3.py', 'sub_dir/', 'sub_dir/bar.py', 'sub_dir/foo.py']

.namelist() возвращает список имен файлов и каталогов в архиве. Чтобы получить информацию о файлах в архиве, используйте .getinfo():

import zipfile

with zipfile.ZipFile('data.zip', 'r') as zipobj:
    bar_info = zipobj.getinfo('sub_dir/bar.py')
    bar_info.file_size

Вот что получится:

15277

.getinfo() возвращает объект ZipInfo, в котором хранится информация об одном члене архива. Чтобы получить информацию о файле в архиве, вы передаете его путь в качестве аргумента в .getinfo(). Используя getinfo(), вы можете получить информацию об участниках архива, например дату последнего изменения файлов, их сжатые размеры, их полные имена файлов. При доступе к .file_size восстанавливается исходный размер файла в байтах.

В следующем примере показано, как получить более подробную информацию об архивных файлах в Python REPL. Предположим, что модуль zipfile уже импортирован, а bar_info — это тот же объект, который вы создали в предыдущих примерах:

>>> bar_info.date_time
(2018, 10, 7, 23, 30, 10)
>>> bar_info.compress_size
2856
>>> bar_info.filename
'sub_dir/bar.py'

bar_info содержит подробную информацию о bar.py, такую ​​как его размер при сжатии и полный путь.

В первой строке показано, как получить дату последнего изменения файла. В следующей строке показано, как получить размер файла после сжатия. Последняя строка показывает полный путь к bar.py в архиве.

ZipFile поддерживает протокол диспетчера контекста,поэтому вы можете использовать его с оператором with. Это автоматически закроет объект ZipFile после того, как вы закончите с ним. Попытка открыть или извлечь файлы из закрытого объекта ZipFile приведет к ошибке.

Извлечение ZIP-архивов   

Модуль zipfile позволяет извлекать один или несколько файлов из архивов ZIP с помощью .extract() и .extractall().

Эти методы по умолчанию извлекают файлы в текущий каталог. Оба они принимают необязательный параметр пути, который позволяет указать другой каталог для извлечения файлов. Если каталог не существует, то он создается автоматически. Чтобы извлечь файлы из архива, выполните следующие действия:

>>> import zipfile
>>> import os

>>> os.listdir('.')
['data.zip']

>>> data_zip = zipfile.ZipFile('data.zip', 'r')

>>> # Извлечь один файл в текущий каталог
>>> data_zip.extract('file1.py')
'/home/terra/test/dir1/zip_extract/file1.py'

>>> os.listdir('.')
['file1.py', 'data.zip']

>>> # Распаковать все файлы в другой каталог
>>> data_zip.extractall(path='extract_dir/')

>>> os.listdir('.')
['file1.py', 'extract_dir', 'data.zip']

>>> os.listdir('extract_dir')
['file1.py', 'file3.py', 'file2.py', 'sub_dir']

>>> data_zip.close()

Третья строка кода — это вызов os.listdir(), который показывает, что в текущем каталоге есть только один файл, data.zip.

Затем открываем data.zip в режиме чтения и вызываете .extract(), чтобы извлечь из него file1.py. .extract() возвращает полный путь к извлеченному файлу. Поскольку путь не указан, .extract() извлекает file1.py в текущий каталог.

В следующей строке печатается список каталогов, показывающий, что текущий каталог теперь включает извлеченный файл в дополнение к исходному архиву. В строке после этого показано, как распаковать весь архив в каталог zip_extract. .extractall() создает extract_dir и извлекает в него содержимое data.zip. Последняя строка закрывает ZIP-архив.

Извлечение данных из архивов, защищенных паролем   

zipfile поддерживает извлечение файлов ZIP, защищенных паролем. Чтобы извлечь защищенные паролем ZIP-файлы, передайте пароль методу .extract() или .extractall() в качестве аргумента:

>>> import zipfile

>>> with zipfile.ZipFile('secret.zip', 'r') as pwd_zip:
...     # Extract from a password protected archive
...     pwd_zip.extractall(path='extract_dir', pwd='Quish3@o')

Открываем архив secret.zip в режиме чтения. Пароль предоставляется в .extractall(), а содержимое архива извлекается в extract_dir. Архив закрывается автоматически после завершения извлечения благодаря оператору with.

Создание новых ZIP-архивов   

Чтобы создать новый ZIP-архив, вы открываете объект ZipFile в режиме записи (w) и добавляете файлы, которые хотите заархивировать:

>>> import zipfile

>>> file_list = ['file1.py', 'sub_dir/', 'sub_dir/bar.py', 'sub_dir/foo.py']
>>> with zipfile.ZipFile('new.zip', 'w') as new_zip:
...     for name in file_list:
...         new_zip.write(name)

В этом примере new_zip открывается в режиме записи, и каждый файл в file_list добавляется в архив. Когда набор операторов with завершается, new_zip закрывается. Открытие ZIP-файла в режиме записи стирает содержимое архива и создает новый архив.

Чтобы добавить файлы в существующий архив, откройте объект ZipFile в режиме добавления, а затем добавьте файлы:

>>> # Открываем объект ZipFile в режиме добавления
>>> with zipfile.ZipFile('new.zip', 'a') as new_zip:
...     new_zip.write('data.txt')
...     new_zip.write('latin.txt')

Здесь вы открываете архив new.zip, созданный в предыдущем примере, в режиме добавления. Открытие объекта ZipFile в режиме добавления позволяет добавлять новые файлы в ZIP-файл, не удаляя его текущее содержимое. После добавления файлов в ZIP-файл оператор with выходит из контекста и закрывает ZIP-файл.

Открытие архивов TAR   

Файлы TAR представляют собой несжатые файловые архивы, такие как ZIP. Их можно сжать с помощью методов сжатия gzip, bzip2 и lzma. Класс TarFile позволяет читать и записывать архивы TAR.

Сделайте это, чтобы прочитать из архива:

import tarfile

with tarfile.open('example.tar', 'r') as tar_file:
    print(tar_file.getnames())

Объекты tarfile открываются, как и большинство файловых объектов. У них есть функция open(), которая принимает режим, определяющий способ открытия файла.

Используйте режимы 'r', 'w' или 'a', чтобы открыть несжатый файл TAR для чтения, записи и добавления соответственно. Чтобы открыть сжатые файлы TAR, передайте в tarfile.open() аргумент mode в формате filemode[:compression]. В таблице ниже перечислены возможные режимы открытия файлов TAR:

Режим Действие
r Открывает архив для чтения с прозрачным сжатием
r:gz Открывает архив для чтения со сжатием gzip
r:bz2 Открывает архив для чтения со сжатием bzip2
r:xz Открывает архив для чтения со сжатием lzma
w Открывает архив для записи без сжатия
w:gz Открывает архив для записи в сжатом формате gzip
w:xz Открывает архив для записи в сжатом формате lzma
а Открывает архив для добавления без сжатия

.open() по умолчанию работает в режиме 'r'. Чтобы прочитать несжатый файл TAR и получить имена файлов в нем, используйте .getnames():

>>> import tarfile

>>> tar = tarfile.open('example.tar', mode='r')
>>> tar.getnames()
['CONTRIBUTING.rst', 'README.md', 'app.py']

Возвращается список с именами содержимого архива.

Примечание. Чтобы показать вам, как использовать различные методы объекта tarfile, файл TAR в примерах открывается и закрывается вручную в интерактивном сеансе REPL.

Такое взаимодействие с файлом TAR позволяет увидеть результат выполнения каждой команды. Обычно вы хотите использовать диспетчер контекста для открытия файловых объектов.

К метаданным каждой записи в архиве можно получить доступ с помощью специальных атрибутов:

>>> for entry in tar.getmembers():
...     print(entry.name)
...     print(' Modified:', time.ctime(entry.mtime))
...     print(' Size    :', entry.size, 'bytes')
...     print()
CONTRIBUTING.rst
 Modified: Sat Nov  1 09:09:51 2018
 Size    : 402 bytes

README.md
 Modified: Sat Nov  3 07:29:40 2018
 Size    : 5426 bytes

app.py
 Modified: Sat Nov  3 07:29:13 2018
 Size    : 6218 bytes

В этом примере вы просматриваете список файлов, возвращаемых .getmembers(), и распечатываете атрибуты каждого файла. Объекты, возвращаемые .getmembers(), имеют атрибуты, к которым можно получить программный доступ, такие как имя, размер и время последнего изменения каждого из файлов в архиве. После чтения или записи в архив,его необходимо закрыть, чтобы освободить системные ресурсы.

Извлечение файлов из архива TAR   

В этом разделе вы узнаете, как извлекать файлы из архивов TAR, используя следующие методы:

  • .extract()
  • .extractfile()
  • .extractall()

Чтобы извлечь отдельный файл из архива TAR, используйте extract(), передав имя файла:

>>> tar.extract('README.md')
>>> os.listdir('.')
['README.md', 'example.tar']

Файл README.md извлекается из архива в файловую систему. Вызов os.listdir() подтверждает, что файл README.md был успешно извлечен в текущий каталог. Чтобы распаковать или извлечь все из архива, используйте .extractall():

>>> tar.extractall(path="extracted/")

.extractall() имеет необязательный аргумент пути, чтобы указать, куда должны идти извлеченные файлы. Здесь архив распаковывается в распакованный каталог. Следующие команды показывают, что архив был успешно извлечен:

$ ls
example.tar  extracted  README.md

$ tree
.
├── example.tar
├── extracted
|   ├── app.py
|   ├── CONTRIBUTING.rst
|   └── README.md
└── README.md

1 directory, 5 files

$ ls extracted/
app.py  CONTRIBUTING.rst  README.md

Чтобы извлечь объект файла для чтения или записи, используйте .extractfile(), который принимает имя файла или объект TarInfo для извлечения в качестве аргумента. .extractfile() возвращает объект в виде файла, который можно читать и использовать:

>>> f = tar.extractfile('app.py')
>>> f.read()
>>> tar.close()

Открытые архивы всегда следует закрывать после того, как они были прочитаны или записаны. Чтобы закрыть архив, вызовите .close() для дескриптора файла архива или используйте оператор with при создании объектов tarfile, чтобы автоматически закрыть архив, когда вы закончите. Это освобождает системные ресурсы и записывает любые изменения, внесенные вами в архив, в файловую систему.

Создание новых архивов TAR   

Вот как это сделать:

>>> import tarfile

>>> file_list = ['app.py', 'config.py', 'CONTRIBUTORS.md', 'tests.py']
>>> with tarfile.open('packages.tar', mode='w') as tar:
...     for file in file_list:
...         tar.add(file)

>>> # Прочитать содержимое вновь созданного архива
>>> with tarfile.open('package.tar', mode='r') as t:
...     for member in t.getmembers():
...         print(member.name)
app.py
config.py
CONTRIBUTORS.md
tests.py

Сначала составляется список файлов, которые нужно добавить в архив, чтобы не приходилось добавлять каждый файл вручную.

В следующей строке с помощью диспетчера контекста открывается новый архив с именем packages.tar в режиме записи. Открытие архива в режиме записи ('w') позволяет вам записывать в архив новые файлы.Все существующие файлы в архиве удаляются и создается новый архив.

После того, как архив создан и заполнен, менеджер контекста с автоматически закрывает его и сохраняет в файловой системе. Последние три строки открывают только что созданный архив и распечатывают имена содержащихся в нем файлов. Чтобы добавить новые файлы в существующий архив, откройте архив в режиме добавления ('a'):

>>> with tarfile.open('package.tar', mode='a') as tar:
...     tar.add('foo.bar')

>>> with tarfile.open('package.tar', mode='r') as tar:
...     for member in tar.getmembers():
...         print(member.name)
app.py
config.py
CONTRIBUTORS.md
tests.py
foo.bar

Открытие архива в режиме добавления позволяет добавлять в него новые файлы, не удаляя уже существующие.

Работа со сжатыми архивами   

tarfile также может читать и записывать архивы TAR, сжатые с использованием сжатия gzip, bzip2 и lzma. Для чтения или записи в сжатый архив используйте tarfile.open(), передав соответствующий режим для типа сжатия.

Например, для чтения или записи данных в архив TAR, сжатый с помощью gzip, используйте режимы 'r:gz' или 'w:gz' соответственно:

>>> files = ['app.py', 'config.py', 'tests.py']
>>> with tarfile.open('packages.tar.gz', mode='w:gz') as tar:
...     tar.add('app.py')
...     tar.add('config.py')
...     tar.add('tests.py')

>>> with tarfile.open('packages.tar.gz', mode='r:gz') as t:
...     for member in t.getmembers():
...         print(member.name)
app.py
config.py
tests.py

Режим 'w:gz' открывает архив для записи, сжатой gzip, а 'r:gz' открывает архив для чтения сжатого gzip. Открытие сжатых архивов в режиме добавления невозможно. Чтобы добавить файлы в сжатый архив, вам необходимо создать новый архив.

Более простой способ создания архивов   

Стандартная библиотека Python также поддерживает создание архивов TAR и ZIP с использованием высокоуровневых методов в модуле shutil. Утилиты архивирования в shutil позволяют создавать, читать и извлекать архивы ZIP и TAR. Эти утилиты полагаются на модули tarfile и zipfile нижнего уровня.

Работа с архивами с помощью shutil.make_archive()

shutil.make_archive() принимает как минимум два аргумента: имя архива и формат архива.

По умолчанию он сжимает все файлы в текущем каталоге в формат архива, указанный в аргументе формата. Вы можете передать необязательный аргумент root_dir для сжатия файлов в другом каталоге. .make_archive() поддерживает zip, tar, bztar, и форматы архивов gztar.

Вот как создать архив TAR с помощью shutil:

import shutil

# shutil.make_archive(base_name, format, root_dir)
shutil.make_archive('data/backup', 'tar', 'data/')

Это копирует все в data/ и создает в файловой системе архив с именем backup.tar и возвращает его имя. Чтобы распаковать архив, вызовите .unpack_archive():

shutil.unpack_archive('backup.tar', 'extract_dir/')

Вызов .unpack_archive() и передача имени архива и каталога назначения извлекает содержимое backup.tar в extract_dir/. ZIP-архивы можно создавать и извлекать таким же образом.

Чтение нескольких файлов   

Python поддерживает чтение данных из нескольких входных потоков или из списка файлов через модуль fileinput. Этот модуль позволяет быстро и легко перебирать содержимое одного или нескольких текстовых файлов. Вот типичный способ использования файлового ввода:

import fileinput
for line in fileinput.input()
    process(line)

fileinput получает входные данные из аргументов командной строки, переданных по умолчанию в sys.argv.

Использование fileinput для перебора нескольких файлов

Давайте воспользуемся fileinput, чтобы создать грубую версию общей утилиты UNIX cat. Утилита cat последовательно читает файлы, записывая их на стандартный вывод. Если в аргументах командной строки указано несколько файлов, cat объединит текстовые файлы и отобразит результат в терминале:

# Файл: fileinput-example.py
import fileinput
import sys

files = fileinput.input()
for line in files:
    if fileinput.isfirstline():
        print(f'\n--- Reading {fileinput.filename()} ---')
    print(' -> ' + line, end='')
print()

Выполнение этого в двух текстовых файлах в моем текущем каталоге дает следующий результат:

$ python3 fileinput-example.py bacon.txt cupcake.txt
--- Reading bacon.txt ---
 -> Spicy jalapeno bacon ipsum dolor amet in in aute est qui enim aliquip,
 -> irure cillum drumstick elit.
 -> Doner jowl shank ea exercitation landjaeger incididunt ut porchetta.
 -> Tenderloin bacon aliquip cupidatat chicken chuck quis anim et swine.
 -> Tri-tip doner kevin cillum ham veniam cow hamburger.
 -> Turkey pork loin cupidatat filet mignon capicola brisket cupim ad in.
 -> Ball tip dolor do magna laboris nisi pancetta nostrud doner.

--- Reading cupcake.txt ---
 -> Cupcake ipsum dolor sit amet candy I love cheesecake fruitcake.
 -> Topping muffin cotton candy.
 -> Gummies macaroon jujubes jelly beans marzipan.

fileinput позволяет получить дополнительную информацию о каждой строке, например, является ли она первой строкой (.isfirstline()), номером строки (.lineno()) и именем файла (.filename()). Вы можете прочитать больше об этом здесь.

Заключение   

Теперь вы знаете, как использовать Python для выполнения наиболее распространенных операций с файлами и группами файлов. Вы узнали о различных встроенных модулях, используемых для чтения, поиска и управления ими.

Теперь вы готовы использовать Python для:

  • Чтения содержимого каталога и свойств файла
  • Создания каталогов и деревьев каталогов.
  • Поиска шаблонов в именах файлов.
  • Создания временных файлов и каталогов.
  • Перемещения, переименования, копирования и удаления файлов или каталогов.
  • Чтения и извлечения данных из архивов разных типов.
  • Чтения нескольких файлов одновременно с использованием файлового ввода.
  • Отмечать, как завершенное

Использованы материалы Working With Files in Python

Опубликовано Вадим В. Костерин

ст. преп. кафедры ЦЭиИТ. Автор более 130 научных и учебно-методических работ. Лауреат ВДНХ (серебряная медаль).

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *