Как скопировать файл в Python

Введение Когда дело доходит до использования Python для копирования файлов, существует два основных способа: использование модуля shutil или модуля os. Все методы операционной системы, которые мы здесь показываем, являются методами, которые позволяют нам выполнять команды оболочки из нашего кода Python, который мы будем использовать для выполнения команды копирования (Windows) или команды cp (Unix). Вы заметите, что многие из этих методов, как в модуле shutil, так и в модуле os, имеют очень похожие функции (что не должно вызывать удивления), но каждый различается по функциям.

Вступление

Когда дело доходит до использования Python для копирования файлов, есть два основных способа: использовать модуль shutil или модуль os Все os которые мы здесь показываем, являются методами, которые позволяют нам выполнять команды оболочки из нашего кода Python, который мы будем использовать для выполнения команды copy (Windows) или команды cp (Unix).

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

Копирование файлов с помощью модуля shutil

Модуль shutil предлагает несколько высокоуровневых методов копирования файлов. Вот основные из них:

копировать файл

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

Синтаксис этого метода:

 shutil.copyfile(src_file, dest_file, *, follow_symlinks=True) 

Например, следующий код скопирует файл с именем file1.txt в файл с именем file2.txt:

 import shutil 
 
 shutil.copyfile('file1.txt', 'file2.txt') 

Одна интересная и потенциально полезная функция shutil.copyfile - логический аргумент follow_symlinks Если установлено значение False и исходный файл является символической ссылкой, то вместо копирования файла будет создана новая символическая ссылка.

копировать

Этот метод очень похож на copyfile , с основным отличием в том, что он не только копирует содержимое исходного файла, но и делает еще один шаг вперед, а также копирует разрешения файловой системы. Копирование прав доступа к файлам - нетривиальная задача для большинства языков программирования, так что это хорошая возможность.

Синтаксис следующий:

 shutil.copy(src_file, dest_file, *, follow_symlinks=True) 

Каждый из этих параметров такой же, как и в методе copyfile Например, следующий код скопирует «file1.txt» в «file3.txt».

 import shutil 
 
 shutil.copy('file1.txt', 'file3.txt') 

Примечание . Убедитесь, что вы не называете свой скрипт таким же, как один из импортируемых модулей (что я ошибочно сделал при тестировании кода для этой статьи). Если вы это сделаете, вы получите сообщение об ошибке при попытке импортировать этот модуль из-за проблемы циклического импорта.

copy2

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

Синтаксис следующий:

 shutil.copy2(src_file, dest_file, *, follow_symlinks=True) 

Опять же, эти параметры такие же, как и в предыдущих командах, которые мы уже упоминали.

Например, следующий код скопирует «file1.txt» в «file4.txt», а также сохранит метаданные исходного файла «file1.txt».

 import shutil 
 
 shutil.copy2('file1.txt', 'file4.txt') 

 $ python copy-files.py 
 $ ls -l 
 total 32 
 -rw-r--r-- 1 scott staff 91 Oct 27 11:26 copy-files.py 
 -rw-r--r-- 1 scott staff 6 Oct 27 11:27 file1.txt 
 -rw-r--r-- 1 scott staff 6 Oct 27 11:29 file3.txt 
 -rw-r--r-- 1 scott staff 6 Oct 27 11:27 file4.txt 

Как видно из выполнения нашего кода выше, «file1.txt» был скопирован в «file4.txt». Однако вы могли заметить, что дата создания была сохранена в новом файле, в отличие от shutil.copy , который копирует «file1.txt» в «file3.txt» и дает ему новую дату создания.

copyfileobj

Этот метод копирует содержимое исходного файла в целевой файл из текущей позиции исходного файла. Это означает, что если вы читаете данные из объекта исходного файла, то позиция, в которой вы прекращаете чтение, - это позиция, с которой copyfileobj начинает копирование.

Синтаксис следующий:

 shutil.copyfileobj(src_file_object, dest_file_object[, length]) 

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

Например, следующий код скопирует "file1.txt" в "file5.txt"

 import shutil 
 
 filename1 = 'file1.txt' 
 fileA = open(filename1, 'rb') 
 
 filename2 = 'file5.txt' 
 fileB = open(filename2, 'wb') 
 
 shutil.copyfileobj(fileA, fileB) 

Как мы видим, чтобы использовать copyfileobj , нам нужно открыть файлы в двоичном режиме (который является частью «b» от «rb» и «wb»). Кроме того, исходный файл должен быть открыт как доступный для чтения, а целевой файл должен быть открыт как доступный для записи (части «r» и «w» соответственно).

Копирование файлов с помощью модуля os

Модуль os предоставляет возможность использовать функциональные возможности операционной системы для копирования ваших файлов. В большинстве (если не во всех) примерах отсюда мы приводим примеры, которые работают как для Windows, так и для Unix. Примеры различаются из-за используемых команд оболочки, поэтому не забудьте обратить внимание на то, как каждый вызов функции помечен в комментариях Python.

открывать

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

Синтаксис следующий:

 os.popen(cmd[, mode[, bufsize]]) 

Здесь возвращаемое значение представляет собой файловый объект, подключенный к каналу. Этот объект может быть прочитан или записан в зависимости от режима. По умолчанию установлен режим «r», который позволяет читать содержимое файла.

В приведенном ниже примере файл file1.txt будет скопирован в file6.txt:

 import os 
 
 # Windows 
 os.popen('copy file1.txt file6.txt') 
 
 # Unix 
 os.popen('cp file1.txt file6.txt') 

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

система

Этот метод выполняет указанную команду в подоболочке. Он доступен как для Unix, так и для Windows. Синтаксис следующий:

 os.system(command) 

Здесь command - это строка, содержащая команду оболочки DOS или Unix. В нашем случае сюда мы поместим команду copy или cp .

Например, следующий код скопирует file1.txt в file7.txt.

 import os 
 
 # Windows 
 os.system('copy file1.txt file7.txt') 
 
 # Unix 
 os.system('cp file1.txt file7.txt') 

Это выглядит идентично предыдущей os.popen мы только что использовали, но команда выполняется в подоболочке, что означает, что она выполняется в отдельном потоке параллельно с вашим исполняемым кодом. Чтобы дождаться его завершения, вам нужно вызвать .wait() для объекта, возвращаемого os.system .

Копирование файлов с помощью модуля подпроцесса

Модуль subprocess предназначен для замены некоторых методов в os (в частности, os.system и os.spawn* ), и он представляет два основных метода доступа к командам операционной системы. Это методы call и check_output . Еще раз, для систем Unix команду «copy file1.txt file2.txt» следует заменить на «cp file1.txt file2.txt».

метод вызова

Документация Python рекомендует нам использовать call для запуска команды из операционной системы.

Синтаксис следующий:

 subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False) 

Параметр args будет включать нашу команду оболочки. Однако небольшое предостережение, поскольку документация Python предупреждает нас, что использование shell=True может представлять угрозу безопасности.

Используя этот вызов функции, мы можем запустить нашу команду копирования следующим образом:

 import subprocess 
 
 # Windows 
 status = subprocess.call('copy file1.txt file8.txt', shell=True) 
 
 # Unix 
 status = subprocess.call('cp file1.txt file8.txt', shell=True) 

Как показано в приведенном выше примере, нам просто нужно передать строку с помощью команды оболочки, как и раньше.

Как и ожидалось, операционная система скопирует file1.txt в файл с именем file8.txt.

check_output Метод

Этот метод также позволяет нам выполнять команду в оболочке. Это очень похоже на subprocess.run , за исключением того, что по умолчанию она передает данные из stdout в виде закодированных байтов. Синтаксис следующий:

 subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False) 

Здесь args включает команду оболочки, которую мы хотим использовать. Еще раз, документация Python предупреждает нас об использовании shell=True , поэтому используйте этот метод с осторожностью.

В следующем коде мы скопируем «file1.txt» в «file9.txt» с помощью команды check_output :

 import subprocess 
 
 # Windows 
 status = subprocess.check_output('copy file1.txt file9.txt', shell=True) 
 
 # Unix 
 status = subprocess.check_output('cp file1.txt file9.txt', shell=True) 

И, как и все команды, которые мы показали в этой статье, это скопирует файл «file1.txt» в указанное нами место назначения, то есть «file9.txt» здесь.

Заключение

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

Не уверены, какой из них вам подходит? Здесь мы представили множество различных способов копирования файлов, так что это понятно. Метод, который вы используете для копирования файла, полностью зависит от вас и зависит от ваших конкретных потребностей. Хотя в большинстве случаев вам подойдет shutil Попробуйте начать с shutil.copy2 и посмотрите, подходит ли он вам.

Какой метод вы используете и почему? Дайте нам знать об этом в комментариях!

comments powered by Disqus