Shutil.copy: примеры (PYTHON)
shutil.copy(src, dst, follow_symlinks): strОписание функции shutil.copy
Функция shutil.copy() в Python используется для копирования содержимого файла из одного местоположения в другое. Она входит в стандартный модуль shutil (утилиты для работы с оболочкой). Основное применение - копирование отдельных файлов, когда не требуется сохранять метаданные, такие как временные метки или права доступа.
Аргументы функции
- src (строка или объект, подобный пути): путь к исходному файлу, который необходимо скопировать. Это обязательный аргумент.
- dst (строка или объект, подобный пути): путь назначения. Может быть именем файла или каталогом. Если dst указывает на каталог, файл будет скопирован в этот каталог с сохранением исходного имени. Если dst указывает на файл, копирование произойдет с новым именем. Это обязательный аргумент.
- follow_symlinks (булево значение, необязательный): если значение True (по умолчанию), функция следует за символическими ссылками в исходном пути. Если False и src является символической ссылкой, будет создана новая символическая ссылка, а не скопировано содержимое файла.
Возвращаемое значение
Функция возвращает строку, представляющую путь к скопированному файлу (тот же, что и переданный в dst).
Примеры использования shutil.copy
Базовое копирование файла
import shutil
import os
# Копирование файла с сохранением имени в текущем каталоге
shutil.copy('source.txt', 'destination.txt')
print(f'Файл создан: {os.path.exists("destination.txt")}')Файл создан: True
Копирование в директорию
import shutil
import os
# Создаем директорию, если ее нет
os.makedirs('backup', exist_ok=True)
# Копируем файл в директорию 'backup' с сохранением имени
result_path = shutil.copy('report.pdf', 'backup')
print(f'Скопировано в: {result_path}')Скопировано в: backup\report.pdf
Копирование с параметром follow_symlinks=False
import shutil
import os
# Создаем символическую ссылку (на Unix-системах)
if os.name != 'nt':
os.symlink('real_file.txt', 'link_file.txt')
# Копируем ссылку как ссылку, а не файл
shutil.copy('link_file.txt', 'copied_link.txt', follow_symlinks=False)
# Проверяем, является ли копия ссылкой
print(f'Копия - символическая ссылка: {os.path.islink("copied_link.txt")}')Копия - символическая ссылка: True
Похожие функции в Python
Модуль shutil предлагает несколько функций для копирования:
- shutil.copy2() - копирует файл, сохраняя метаданные (время последнего доступа и модификации). Используется, когда важна информация о времени изменения файла.
- shutil.copyfile() - копирует содержимое файла в другой файл без поддержки копирования в директорию или обработки метаданных. Более низкоуровневая функция.
- shutil.copytree() - рекурсивно копирует целое дерево каталогов. Применяется для копирования папок со всем содержимым.
- os.popen() или subprocess.run() с вызовом системных команд (например, cp на Unix) - дают полный контроль над процессом копирования, но менее переносимы.
Выбор функции зависит от задачи: shutil.copy() подходит для быстрого копирования файлов без метаданных, shutil.copy2() - для случаев, когда нужно сохранить временные метки, а shutil.copytree() - для копирования директорий.
Аналоги функции в других языках
JavaScript (Node.js)
Используется модуль fs с функцией copyFile(). Работает асинхронно.
const fs = require('fs/promises');
async function copyFileExample() {
await fs.copyFile('source.txt', 'destination.txt');
console.log('Файл скопирован');
}
copyFileExample();Файл скопирован
Java
Класс Files с методом copy(). Требует указания пути через Path объекты.
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws Exception {
Path source = Paths.get("source.txt");
Path destination = Paths.get("destination.txt");
Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Файл скопирован");
}
}Файл скопирован
PHP
Функция copy(). Проста в использовании, но не поддерживает дополнительные флаги.
<?php
copy('source.txt', 'destination.txt');
echo "Файл скопирован";
?>Файл скопирован
C#
Метод File.Copy() из пространства имен System.IO.
using System.IO;
class Program {
static void Main() {
File.Copy("source.txt", "destination.txt", overwrite: true);
System.Console.WriteLine("Файл скопирован");
}
}Файл скопирован
Golang
Используется функция Copy() из пакета io или CopyFile() из os.
package main
import (
"io"
"os"
)
func main() {
source, _ := os.Open("source.txt")
destination, _ := os.Create("destination.txt")
io.Copy(destination, source)
source.Close()
destination.Close()
println("Файл скопирован")
}Файл скопирован
Типичные ошибки при использовании
Файл источника не существует
import shutil
import traceback
try:
shutil.copy('несуществующий_файл.txt', 'destination.txt')
except FileNotFoundError as e:
print(f'Ошибка: {e}')Ошибка: [Errno 2] No such file or directory: 'несуществующий_файл.txt'
Отсутствие прав на чтение исходного файла
import shutil
import os
# Создаем файл без прав на чтение (Unix-системы)
if os.name != 'nt':
with open('protected.txt', 'w') as f:
f.write('секрет')
os.chmod('protected.txt', 0o000) # Нет прав
try:
shutil.copy('protected.txt', 'copy.txt')
except PermissionError as e:
print(f'Ошибка прав: {e}')
finally:
os.chmod('protected.txt', 0o644) # Восстановление прав
os.remove('protected.txt')Ошибка прав: [Errno 13] Permission denied: 'protected.txt'
Копирование в несуществующую директорию
import shutil
try:
shutil.copy('source.txt', 'несуществующая_папка/copy.txt')
except FileNotFoundError as e:
print(f'Ошибка: {e}')Ошибка: [Errno 2] No such file or directory: 'несуществующая_папка/copy.txt'
Изменения в последних версиях Python
Функция shutil.copy() стабильна и не претерпела значительных изменений в последних основных версиях Python. Однако с версии Python 3.3 функция поддерживает аргумент follow_symlinks, который позволяет контролировать обработку символических ссылок. В Python 3.8 улучшена обработка ошибок при работе с специальными файлами (например, символьными устройствами в Unix). Также, начиная с Python 3.10, улучшены сообщения об ошибках для некоторых сценариев, связанных с правами доступа.
Расширенные примеры использования
Копирование с проверкой размера файла
import shutil
import os
def copy_if_small(src, dst, max_size=1024*1024): # 1 MB
if os.path.getsize(src) <= max_size:
return shutil.copy(src, dst)
else:
raise ValueError(f'Файл {src} превышает максимальный размер {max_size} байт')
# Пример использования
try:
result = copy_if_small('large_video.mp4', 'backup.mp4', max_size=5000000)
print(f'Успешно скопирован: {result}')
except ValueError as e:
print(f'Ошибка: {e}')Ошибка: Файл large_video.mp4 превышает максимальный размер 5000000 байт
Копирование с ведением лога
import shutil
import logging
import datetime
logging.basicConfig(filename='copy_log.log', level=logging.INFO)
def logged_copy(src, dst):
try:
result = shutil.copy(src, dst)
logging.info(f'{datetime.datetime.now()}: Успешное копирование из {src} в {dst}')
return result
except Exception as e:
logging.error(f'{datetime.datetime.now()}: Ошибка при копировании {src} -> {dst}: {e}')
raise
# Пример
logged_copy('data.csv', 'backup/data.csv')# В файле copy_log.log появится запись: # 2023-10-05 14:30:15.123456: Успешное копирование из data.csv в backup/data.csv
Копирование файлов только определенного типа
import shutil
import os
def copy_only_ext(src_dir, dst_dir, extension):
os.makedirs(dst_dir, exist_ok=True)
for filename in os.listdir(src_dir):
if filename.endswith(extension):
src_path = os.path.join(src_dir, filename)
dst_path = os.path.join(dst_dir, filename)
shutil.copy(src_path, dst_path)
print(f'Скопирован: {filename}')
copy_only_ext('documents', 'backup_docs', '.pdf')Скопирован: report1.pdf Скопирован: manual.pdf
Копирование с обработкой символических ссылок в директории
import shutil
import os
# Создаем структуру для примера (Unix)
if os.name != 'nt':
os.makedirs('test_dir', exist_ok=True)
with open('test_dir/real.txt', 'w') as f:
f.write('content')
os.symlink('real.txt', 'test_dir/link.txt')
# Копируем файл, следуя символьным ссылкам
shutil.copy('test_dir/link.txt', 'copy1.txt', follow_symlinks=True)
# Копируем как символьную ссылку
shutil.copy('test_dir/link.txt', 'copy2.txt', follow_symlinks=False)
print(f'copy1 - это ссылка: {os.path.islink("copy1.txt")}')
print(f'copy2 - это ссылка: {os.path.islink("copy2.txt")}')
# Очистка
os.remove('copy1.txt')
os.remove('copy2.txt')
shutil.rmtree('test_dir')copy1 - это ссылка: False copy2 - это ссылка: True