Документация Python неофициальный перевод
Содержание страницы

10.10. shutil – высокоуровневые операции с файламиshutil – High-level file operations

Исходный код: Lib/shutil.py


Модуль shutil предоставляет ряд высокоуровневых операций с файлами и наборами файлов. В частности, предоставлены функции, которые поддерживают копирование и удаление файлов. Для операций с отдельными файлами см. также модуль os.

Предупреждение

Даже функции копирования файлов более высокого уровня (shutil.copy(), shutil.copy2()) не могут скопировать все метаданные файла.

На платформах POSIX это означает, что владелец и группа файла теряются, а также ACL. На Mac OS не используются ресурсные форки и другие метаданные. Это означает, что ресурсы будут потеряны, а коды типа и создателя файла будут некорректными. В Windows владельцы файлов, ACL и альтернативные потоки данных не копируются.

10.10.1. Операции с каталогами и файламиDirectory and files operations

shutil.copyfileobj(fsrc, fdst[, length])

Копирует содержимое файлоподобного объекта fsrc в файлоподобный объект fdst. Целое число length, если задано, определяет размер буфера. В частности, отрицательное значение length означает копирование данных без разбиения исходных данных на части; по умолчанию данные читаются порциями, чтобы избежать неконтролируемого расхода памяти. Обратите внимание: если текущая позиция в файле объекта fsrc не равна 0, будут скопированы только данные от текущей позиции до конца файла.

shutil.copyfile(src, dst)

Копирует содержимое (без метаданных) файла с именем src в файл с именем dst. dst должно быть полным именем целевого файла; см. shutil.copy() для копирования, принимающего целевой каталог. Если src и dst – один и тот же файл, возбуждается Error. Целевое расположение должно быть доступно для записи; в противном случае будет возбуждено исключение IOError. Если dst уже существует, он будет заменён. Специальные файлы, такие как символьные или блочные устройства и каналы, не могут быть скопированы этой функцией. src и dst – пути, заданные строками.

shutil.copymode(src, dst)

Копирует биты разрешений из src в dst. Содержимое файла, владелец и группа не изменяются. src и dst – пути, заданные в виде строк.

shutil.copystat(src, dst)

Копирует биты разрешений, время последнего доступа, время последнего изменения и флаги из src в dst. Содержимое файла, владелец и группа не изменяются. src и dst – пути, заданные в виде строк.

shutil.copy(src, dst)

Копирует файл src в файл или каталог dst. Если dst – каталог, в указанном каталоге создаётся (или перезаписывается) файл с тем же базовым именем, что и src. Биты разрешений копируются. src и dst – пути, заданные в виде строк.

shutil.copy2(src, dst)

Идентично copy(), за исключением того, что copy2() также пытается сохранить метаданные файла.

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

shutil.ignore_patterns(*patterns)

Эта фабричная функция создаёт функцию, которую можно использовать как вызываемый объект для аргумента ignore функции copytree(), игнорируя файлы и каталоги, соответствующие одному из предоставленных шаблонов в стиле glob. См. пример ниже.

Новое в версии 2.6.

shutil.copytree(src, dst, symlinks=False, ignore=None)

Рекурсивно копирует всё дерево каталогов с корнем в src. Целевой каталог с именем dst не должен существовать; он будет создан вместе с отсутствующими родительскими каталогами. Права доступа и временные метки каталогов копируются с помощью copystat(), отдельные файлы копируются с помощью shutil.copy2().

Если symlinks равен true, символические ссылки в исходном дереве представлены как символические ссылки в новом дереве, но метаданные исходных ссылок НЕ копируются; если false или не задано, содержимое и метаданные файлов, на которые указывают ссылки, копируются в новое дерево.

Если задан ignore, это должен быть вызываемый объект, который будет получать в качестве аргументов каталог, обрабатываемый copytree(), и список его содержимого, возвращённый os.listdir(). Поскольку copytree() вызывается рекурсивно, вызываемый объект ignore будет вызываться один раз для каждого копируемого каталога. Вызываемый объект должен возвращать последовательность имён каталогов и файлов относительно текущего каталога (т.е. подмножество элементов из его второго аргумента); эти имена будут игнорироваться в процессе копирования. ignore_patterns() можно использовать для создания такого вызываемого объекта, который игнорирует имена на основе шаблонов в стиле glob.

Если возникают исключения, вызывается Error со списком причин.

Данный исходный код следует рассматривать скорее как пример, а не как универсальный инструмент.

Изменено в версии 2.3: Error возбуждается, если при копировании возникают исключения, вместо вывода сообщения.

Изменено в версии 2.5: Создаёт промежуточные каталоги, необходимые для создания dst, вместо возбуждения ошибки. Копирует права доступа и временные метки каталогов с помощью copystat().

Изменено в версии 2.6: Добавлен аргумент ignore для возможности влиять на то, что копируется.

shutil.rmtree(path[, ignore_errors[, onerror]])

Удаляет целое дерево каталогов; path должен указывать на каталог (но не на символическую ссылку на каталог). Если ignore_errors равен true, ошибки, возникающие при неудачном удалении, игнорируются; если false или не указан, такие ошибки обрабатываются вызовом обработчика, заданного onerror, или, если он не указан, вызывается исключение.

Если onerror указан, он должен быть вызываемым объектом, принимающим три параметра: function, path и excinfo. Первый параметр, function, – это функция, возбудившая исключение; это будет os.path.islink(), os.listdir(), os.remove() или os.rmdir(). Второй параметр, path, – это имя пути, переданное функции function. Третий параметр, excinfo, – это информация об исключении, возвращаемая sys.exc_info(). Исключения, возбуждённые onerror, не перехватываются.

Изменено в версии 2.6: Явно проверяет, является ли path символической ссылкой, и возбуждает OSError в этом случае.

shutil.move(src, dst)

Рекурсивно перемещает файл или каталог (src) в другое место (dst).

Если назначение – существующий каталог, то src перемещается внутрь этого каталога. Если назначение уже существует, но не является каталогом, оно может быть перезаписано в зависимости от семантики os.rename().

Если целевой объект находится в текущей файловой системе, то используется os.rename(). В противном случае src копируется (с помощью shutil.copy2()) в dst, а затем удаляется.

Новое в версии 2.3.

exception shutil.Error

Это исключение собирает исключения, возникающие во время операции с несколькими файлами. Для copytree() аргумент исключения представляет собой список кортежей из трёх элементов (srcname, dstname, исключение).

Новое в версии 2.3.

10.10.1.1. пример copytreecopytree example

Этот пример представляет собой реализацию функции copytree(), описанной выше, с опущенной строкой документации. Он демонстрирует многие другие функции, предоставляемые этим модулем.

def copytree(src, dst, symlinks=False, ignore=None):
    names = os.listdir(src)
    if ignore is not None:
        ignored_names = ignore(src, names)
    else:
        ignored_names = set()

    os.makedirs(dst)
    errors = []
    for name in names:
        if name in ignored_names:
            continue
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks, ignore)
            else:
                copy2(srcname, dstname)
            # XXX Что насчет устройств, сокетов и т.д.?
        except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))
        # перехватываем ошибку от рекурсивного copytree, чтобы мы могли
        # продолжить с другими файлами
        except Error as err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except WindowsError:
        # не удается скопировать время доступа к файлам в Windows
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)

Ещё один пример, использующий вспомогательную функцию ignore_patterns():

from shutil import copytree, ignore_patterns

copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))

При этом будет скопировано всё, кроме файлов .pyc и файлов или каталогов, имена которых начинаются с tmp.

Ещё один пример, использующий аргумент ignore для добавления вызова журналирования:

from shutil import copytree
import logging

def _logpath(path, names):
    logging.info('Working in %s' % path)
    return []   # ничего не будет проигнорировано

copytree(source, destination, ignore=_logpath)

10.10.2. Операции архивированияArchiving operations

Также предоставляются высокоуровневые утилиты для создания и чтения сжатых и архивных файлов. Они основаны на модулях zipfile и tarfile.

shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]])

Создаёт архивный файл (например, zip или tar) и возвращает его имя.

base_name – это имя создаваемого файла, включая путь, без расширения, специфичного для формата. format – это формат архива: один из «zip» (если доступен модуль zlib или внешняя программа zip), «tar», «gztar» (если доступен модуль zlib), или «bztar» (если доступен модуль bz2).

root_dir – это каталог, который будет корневым каталогом архива; т.е. мы обычно переходим в root_dir перед созданием архива.

base_dir – это каталог, с которого начинается архивация; т.е. base_dir будет общим префиксом для всех файлов и каталогов в архиве.

root_dir и base_dir по умолчанию равны текущему каталогу.

owner и group используются при создании tar-архива. По умолчанию используются текущий владелец и группа.

logger должен быть объектом, совместимым с PEP 282, обычно экземпляром logging.Logger.

Новое в версии 2.7.

shutil.get_archive_formats()

Возвращает список поддерживаемых форматов архивации. Каждый элемент возвращаемой последовательности – это кортеж (name, description).

По умолчанию shutil предоставляет следующие форматы:

  • zip: ZIP-файл (если доступен модуль zlib или внешняя программа zip).

  • tar: несжатый tar-файл.

  • gztar: tar-файл, сжатый gzip (если доступен модуль zlib).

  • bztar: tar-файл, сжатый bzip2 (если доступен модуль bz2).

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

Новое в версии 2.7.

shutil.register_archive_format(name, function[, extra_args[, description]])

Регистрирует архиватор для формата name. function – это вызываемый объект, который будет использоваться для вызова архиватора.

Если указан, extra_args – это последовательность (name, value), которая будет использоваться как дополнительные ключевые аргументы при использовании вызываемого архиватора.

description используется get_archive_formats(), которая возвращает список архиваторов. По умолчанию – пустой список.

Новое в версии 2.7.

shutil.unregister_archive_format(name)

Удалите имя формата архива name из списка поддерживаемых форматов.

Новое в версии 2.7.

10.10.2.1. Пример архивированияArchiving example

В этом примере мы создаём tar-архив, сжатый gzip, содержащий все файлы, найденные в каталоге .ssh пользователя:

>>> from shutil import make_archive
>>> import os
>>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
>>> root_dir = os.path.expanduser(os.path.join('~', '.ssh'))
>>> make_archive(archive_name, 'gztar', root_dir)
'/Users/tarek/myarchive.tar.gz'

Полученный архив содержит:

$ tar -tzvf /Users/tarek/myarchive.tar.gz
drwx------ tarek/staff       0 2010-02-01 16:23:40 ./
-rw-r--r-- tarek/staff     609 2008-06-09 13:26:54 ./authorized_keys
-rwxr-xr-x tarek/staff      65 2008-06-09 13:26:54 ./config
-rwx------ tarek/staff     668 2008-06-09 13:26:54 ./id_dsa
-rwxr-xr-x tarek/staff     609 2008-06-09 13:26:54 ./id_dsa.pub
-rw------- tarek/staff    1675 2008-06-09 13:26:54 ./id_rsa
-rw-r--r-- tarek/staff     397 2008-06-09 13:26:54 ./id_rsa.pub
-rw-r--r-- tarek/staff   37192 2010-02-06 18:23:10 ./known_hosts