
Копирование файлов в Python можно реализовать несколькими методами: от встроенных функций стандартной библиотеки до специализированных модулей. Выбор подхода зависит от задачи: копирование только содержимого, сохранение метаданных или перенос больших файлов с минимальной нагрузкой на память.
shutil.copy обеспечивает базовое копирование содержимого и прав доступа. Если требуется полное сохранение метаданных, включая временные метки, стоит использовать shutil.copy2. Для ситуаций, когда нужно работать исключительно с бинарными потоками, подойдут методы чтения и записи через open().
При работе с крупными файлами рекомендуется использовать shutil.copyfileobj, который позволяет управлять размером буфера и тем самым контролировать производительность. В системах, где важна скорость, можно рассмотреть использование os.sendfile, доступного в Linux, что позволяет копировать данные на уровне ядра.
Копирование файла с помощью shutil.copy

Функция shutil.copy(src, dst) копирует файл из источника src в место назначения dst, сохраняя содержимое и права доступа. Если в качестве dst указать папку, файл будет создан с тем же именем, что и в исходном пути.
Пример использования:
import shutil
shutil.copy("data/source.txt", "backup/")
shutil.copy("data/source.txt", "backup/copy.txt")
Функция не копирует метаданные, такие как время изменения и права владельца. Для их сохранения применяют shutil.copy2.
| Функция | Сохраняет содержимое | Сохраняет права доступа | Сохраняет метаданные |
|---|---|---|---|
| shutil.copy | Да | Да | Нет |
| shutil.copy2 | Да | Да | Да |
Рекомендуется использовать shutil.copy при необходимости быстрой копии без сохранения временных атрибутов и системных меток.
Использование shutil.copy2 для сохранения метаданных

Функция shutil.copy2() копирует не только содержимое файла, но и метаданные: временные метки создания, изменения и доступа, а также права доступа. Это полезно при резервном копировании или переносе файлов, когда требуется полное сохранение атрибутов.
Пример использования:
import shutil
shutil.copy2("source.txt", "backup/source.txt")
Если целевой каталог не существует, его нужно создать заранее, так как copy2() не создает структуру директорий автоматически. При копировании в существующую папку можно указать только путь к директории – имя файла сохранится исходным.
copy2() опирается на функции операционной системы, поэтому точность сохранения метаданных зависит от платформы. На Windows корректно передаются атрибуты времени и права доступа, на Linux также сохраняются владельцы и группы при наличии прав у пользователя.
Применение shutil.copyfile для точного копирования содержимого

Функция shutil.copyfile(src, dst) копирует байтовое содержимое файла из источника в новый файл назначения. При этом метаданные (права доступа, время изменения) не переносятся, копируется только содержимое.
Основные особенности:
- требуются два обязательных аргумента: путь к исходному файлу и путь к целевому файлу;
- если файл назначения существует, он будет перезаписан без предупреждения;
- если в целевом пути указана директория, будет вызвано исключение
IsADirectoryError;
Пример использования:
import shutil
shutil.copyfile("data/input.txt", "backup/input_copy.txt")
Рекомендации при применении:
- Перед вызовом проверяйте существование исходного файла через
os.path.isfile(). - Используйте абсолютные пути для уменьшения риска ошибок при запуске из разных директорий.
- При работе с большими файлами оборачивайте вызов в
try/exceptдля корректной обработки ошибок. - Для одновременного копирования содержимого и прав доступа используйте
shutil.copy(), а неcopyfile().
Копирование файлов с помощью pathlib

Модуль pathlib предоставляет объектно-ориентированный интерфейс для работы с путями. Самостоятельного метода копирования он не содержит, поэтому применяется связка с shutil.copy2, которая сохраняет метаданные файла.
Пример использования:
from pathlib import Path
import shutil
src = Path("data/source.txt")
dst = Path("backup/source.txt")
shutil.copy2(src, dst)
Объекты Path удобны при формировании путей: dst.parent.mkdir(parents=True, exist_ok=True) позволяет создать недостающие директории перед копированием. Такой подход уменьшает количество ошибок при работе с путями в разных операционных системах.
Для проверки факта копирования можно использовать dst.exists() или сравнить размер исходного и конечного файлов через src.stat().st_size и dst.stat().st_size.
Чтение и запись файлов через open()

Функция open() открывает файл и возвращает объект, с которым можно работать в режимах чтения и записи. Для копирования удобно использовать поочередное чтение и запись строк или блоков данных.
Пример построчного копирования:
with open("source.txt", "r", encoding="utf-8") as src, \
open("copy.txt", "w", encoding="utf-8") as dst:
for line in src:
dst.write(line)
Если требуется обработка бинарных данных (изображения, архивы), используется режим «rb» и «wb»:
with open("source.bin", "rb") as src, \
open("copy.bin", "wb") as dst:
while chunk := src.read(4096):
dst.write(chunk)
Чтение блоками повышает скорость работы с крупными файлами и снижает расход памяти. Размер блока можно регулировать в зависимости от характеристик системы и файла.
Рекомендуется всегда применять конструкцию with, так как она автоматически закрывает файлы и предотвращает утечки ресурсов.
Копирование бинарных файлов блоками

Пример чтения и записи блоками:
block_size = 1024 * 128 # 128 КБ
with open('source.bin', 'rb') as src, open('dest.bin', 'wb') as dst:
while True:
chunk = src.read(block_size)
if not chunk:
break
dst.write(chunk)
Выбор размера блока зависит от объёма файла и доступной памяти. Для небольших файлов (<10 МБ) разница в скорости минимальна, но для гигабайтных файлов блоки 128–256 КБ заметно ускоряют процесс.
При копировании бинарных файлов важно не использовать текстовые режимы (‘r’, ‘w’), иначе произойдёт изменение байтовых значений. Для проверки корректности после копирования можно сравнить контрольные суммы MD5 исходного и скопированного файлов.
Метод блочного копирования совместим с потоковой обработкой данных и позволяет интегрировать прогресс-бар или параллельное сжатие без увеличения потребления оперативной памяти.
Вопрос-ответ:
Как скопировать файл в Python с помощью стандартной библиотеки?
В Python есть модуль shutil, который предоставляет функцию copy(). Она позволяет скопировать содержимое одного файла в другой. Пример использования: shutil.copy('source.txt', 'destination.txt'). Файл будет скопирован вместе с данными, но права доступа и метаданные могут не сохраняться.
Можно ли скопировать файл с сохранением прав доступа и времени изменения?
Да, для этого в модуле shutil есть функция copy2(). Она работает аналогично copy(), но дополнительно сохраняет метаданные файла, включая права доступа, время создания и изменения. Пример: shutil.copy2('source.txt', 'destination.txt'). Такой метод полезен, если важно сохранить точную копию файла.
Как скопировать файл построчно без использования shutil?
Можно открыть исходный и целевой файлы с помощью встроенной функции open() и скопировать данные в цикле. Например: with open('source.txt', 'r') as src, open('destination.txt', 'w') as dst: for line in src: dst.write(line). Этот способ удобен для работы с текстовыми файлами, особенно если нужно обработать строки перед записью.
Существуют ли альтернативные способы копирования файлов через Python?
Да, кроме shutil и построчного чтения, можно использовать модуль pathlib. Он предоставляет метод write_bytes() и read_bytes(), который позволяет прочитать файл как байты и записать их в новый файл. Пример: from pathlib import Path; data = Path('source.txt').read_bytes(); Path('destination.txt').write_bytes(data). Этот метод полезен для бинарных файлов и небольших текстовых файлов.
