Рубрики
Без рубрики

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

Автор оригинала: Scott Robinson.

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

Вступление

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

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

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

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

copyfile

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

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

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)

Каждый из этих параметров такой же, как и в методе copy file . Например, следующий код будет копировать “file1.txt” в “file3.txt”.

import shutil

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

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

copy2

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

Синтаксис выглядит следующим образом:

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])

Значения параметров исходного и целевого файлов аналогичны предыдущим командам, но теперь они относятся к объектам. Параметр 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 предоставляет возможность использовать функциональные возможности операционной системы для копирования ваших файлов. В большинстве (если не во всех) примеров мы приводим примеры, которые работают как для 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 команда “копировать 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 и посмотрите, делает ли это то, что вам нужно.

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