





shutil имеет много методов, которые вы можете использовать. Один из них:
from shutil import copyfile
copyfile(src, dst)
src в файл dst.IOError.dst уже существует, он будет заменен.copy, src и dst - это пути, заданные как str.Еще один метод shutil - shutil.copy2(). Он похож, но сохраняет больше метаданных (например, отметок времени).
Если вы используете операции os.path, используйте copy, а не copyfile. copyfile принимает только строки.
в копии (src, dst) dst может быть каталогом.
Обратите внимание, что не все метаданные будут скопированы, в зависимости от вашей платформы.
Обратите внимание, что это не атомарная операция. Будьте осторожны, используя его в многопоточном приложении.
Обратите внимание, что он не может обрабатывать сокращения, такие как ~, но может работать с относительными путями.
@Owen Действительно может, но каталог уже должен существовать. Кстати, пока целевой каталог уже существует, dst может заканчиваться или не заканчиваться косой чертой в конце, это не имеет значения.
Чтобы создать все целевые каталоги промежуточного уровня, вы можете использовать os.makedirs () перед копированием, подробности здесь stackoverflow.com/questions/12842997/…
shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
В Python 3.8 это значительно увеличило скорость (примерно на 50% быстрее, в зависимости от ОС).
copy или copyfile, похоже, не заменяют файл, если dst уже существует ?. Получение SameFileError
Если вы хотите, чтобы несколько изображений помогли с ясностью: ao.gl/how-to-copy-a-file-in-python
Используйте модуль shutil.
copyfile(src, dst)
Скопируйте содержимое файла с именем src в файл с именем dst. Место назначения должно быть доступно для записи; в противном случае возникнет исключение IOError. Если dst уже существует, он будет заменен. Специальные файлы, такие как символьные или блочные устройства и каналы, не могут быть скопированы с помощью этой функции. src и dst - имена путей, заданные в виде строк.
Взгляните на filesys для всех функций обработки файлов и каталогов, доступных в стандартных модулях Python.
shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
copy2(src,dst) часто более полезен, чем copyfile(src,dst), потому что:
dst быть каталог (вместо полного целевого имени файла), и в этом случае базовое имяsrc используется для создания нового файла;Вот небольшой пример:
import shutil
shutil.copy2('/src/dir/file.ext', '/dst/dir/newname.ext') # complete target filename given
shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext
Я пытаюсь случайным образом скопировать 100k файлов из 1 миллиона файлов. copyfile значительно быстрее copy2
Правильно ли я предполагаю, что shutil.copy2('/dir/file.ext', '/new/dir/') (с косой чертой после целевого пути) устранит двусмысленность относительно того, следует ли копировать в новый файл с именем «dir» или поместить файл в каталог с этим именем?
@Vijay Я считаю, что эти накладные расходы связаны с копированием метаданных.
@Zak Нет двусмысленности, если /new/dir - существующий каталог, см. Комментарий @ MatthewAlpert.
@Zak Вы правы, добавление косой черты в конце устраняет двусмысленность. Если /new/dir/ не существует, Python выдаст IsADirectoryError, в противном случае он копирует файл в /new/dir/ под исходным именем.
shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
Копирование файла - относительно простая операция, как показано в примерах ниже, но вместо этого вы должны использовать для этого модуль shutil stdlib.
def copyfileobj_example(source, dest, buffer_size=1024*1024):
"""
Copy a file from source to dest. source and dest
must be file-like objects, i.e. any object with a read or
write method, like for example StringIO.
"""
while True:
copy_buffer = source.read(buffer_size)
if not copy_buffer:
break
dest.write(copy_buffer)
Если вы хотите скопировать по имени файла, вы можете сделать что-то вроде этого:
def copyfile_example(source, dest):
# Beware, this example does not handle any edge cases!
with open(source, 'rb') as src, open(dest, 'wb') as dst:
copyfileobj_example(src, dst)
Некоторое время назад я заметил, что модуль называется shutil (единственное число), а не shutils (множественное число), и действительно, это является в Python 2.3. Тем не менее, я оставляю эту функцию здесь в качестве примера.
Копирование содержание файла - простая операция. Копировать файл с его метаданными совсем непросто, тем более, если вы хотите быть кроссплатформенным.
Истинный. Глядя на документацию shutil, функция copyfile также не копирует метаданные.
Кстати, если вы хотите скопировать содержимое между двумя файловыми объектами, есть shutil.copyfileobj(fsrc, fdst)
Да, я не уверен, почему бы вам просто не скопировать исходный код shutil.copyfileobj. Кроме того, у вас нет try, finally для обработки закрытия файлов после исключений. Я бы сказал, однако, что ваша функция вообще не должна отвечать за открытие и закрытие файлов. Это должно быть в функции-оболочке, например, как shutil.copyfile оборачивает shutil.copyfileobj.
В приведенном выше коде должен быть указан dest для записи: open(dest, 'wb')
@pi., для копирования метаданных у нас есть shutil.copy() и shutil.copy2(). stackoverflow.com/a/44996087/2445204
Пример копирования каталогов и файлов - из материалов Тима Голдена о Python:
http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html
import os
import shutil
import tempfile
filename1 = tempfile.mktemp (".txt")
open (filename1, "w").close ()
filename2 = filename1 + ".copy"
print filename1, "=>", filename2
shutil.copy (filename1, filename2)
if os.path.isfile (filename2): print "Success"
dirname1 = tempfile.mktemp (".dir")
os.mkdir (dirname1)
dirname2 = dirname1 + ".copy"
print dirname1, "=>", dirname2
shutil.copytree (dirname1, dirname2)
if os.path.isdir (dirname2): print "Success"
Вы можете использовать os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
или как я это сделал,
os.system('cp '+ rawfile + ' rawdata.dat')
где rawfile - это имя, которое я создал внутри программы.
Это решение только для Linux
это не переносимо и не нужно, так как вы можете просто использовать shutil.
Даже когда shutil недоступен - subprocess.run() (без shell=True!) Является лучшей альтернативой os.system().
shutil более портативный
subprocess.run(), предложенный @maxschlepzig, - большой шаг вперед при вызове внешних программ. Однако для гибкости и безопасности используйте форму ['cp', rawfile, 'rawdata.dat'] для передачи командной строки. (Однако для копирования рекомендуется использовать shutil и его друзья, а не вызывать внешнюю программу.)
попробуйте это с именами файлов с пробелами.
| Функция | Копирует метаданные | Копии разрешений | Использует файловый объект | Destination может быть каталогом |
|---|---|---|---|---|
| shutil.copy | Нет | да | Нет | да |
| shutil.copyfile | Нет | Нет | Нет | Нет |
| shutil.copy2 | да | да | Нет | да |
| shutil.copyfileobj | Нет | Нет | да | Нет |
предоставляет ли shutil копию с режимом добавления в место назначения вместо перезаписи?
Что означает «Может использовать буфер»?
@lucidbrot - Если проверять это - The integer length, if given, is the buffer size. In particular, a negative length value means to copy the data without looping over the source data in chunks; by default the data is read in chunks to avoid uncontrolled memory consumption.
Это довольно неточно, извините. shutil будет использовать копирование данных по частям в любом случае. Например. copy2 вызывает copyfile(), который, в свою очередь, вызывает copyfileobj(), который выполняет копирование по частям. Единственное отличие: copyfileobj() позволяет явно указать размер буфера (при желании), другие функции просто используют размер буфера по умолчанию shutil и не предлагают возможности его настройки. Таким образом, столбец «можно использовать буфер» не имеет никакого смысла. Буфер используется все время. Если для -1 указан copyfileobj, он будет такого же размера, как и сам файл.
@RegisMay - Спасибо за комментарий. Так что лучше поменять can use buffer на can specify buffer?
@jezrael: Нет. Если вы хотите что-то указать, вам нужно будет назвать это can specify buffer size. Но в этом нет особого смысла: размер буфера очень разумный, поэтому нет необходимости в каких-либо изменениях. Обычным пользователям просто не нужно менять размер буфера. Если это будет проблемой для вас, чтобы вы подумали об изменении размера буфера, вы, скорее всего, все равно решите отказаться от python и flask для своего проекта, поскольку изменение размера буфера не поможет вам в достаточной степени, если у вас есть какие-либо проблемы с производительностью. . Моя рекомендация: удалите этот столбец ;-)
@jezrael: Ненавижу это говорить, но с модулями Python всегда полезно взглянуть на код. Так быть не должно, поскольку должно быть достаточно хорошо написанной документации, чтобы узнать о модуле без, глядя на код. Но с модулями Python всегда полезно смотреть на код.
@RegisMay - я проверяю аналогичный ответ ниже, и кажется, что это было решено путем изменения can use buffer на accepts file obj. Думаю, в этом главное отличие обоих ответов. Поэтому, на мой взгляд, вместо удаления лучше переименовать его.
@jezrael: Делай как хочешь, но я думаю, что лучше удалить. Для обычных пользователей Python НИКОГДА НЕ НУЖНО изменять размер буфера, если он / она хочет скопировать файлы. Скорее всего, авторы shutils чувствовали то же самое: вероятно, именно по этой причине: а) вы не можете указать размер буфера во время копирования; б) и нет никакого способа изменить его в целом. Так что эта информация скорее вводит в заблуждение, чем помогает. Обычно вы НЕ захотите читать полные данные файла в память, если собираетесь копировать файлы.
Для больших файлов я прочитал файл построчно и прочитал каждую строку в массив. Затем, когда массив достигнет определенного размера, добавьте его в новый файл.
for line in open("file.txt", "r"):
list.append(line)
if len(list) == 1000000:
output.writelines(list)
del list[:]
это кажется немного избыточным, поскольку писатель должен обрабатывать буферизацию. for l in open('file.txt','r'): output.write(l) должен работать найти; просто настройте буфер выходного потока в соответствии с вашими потребностями. или вы можете переходить по байтам, повторяя попытку с output.write(read(n)); output.flush(), где n - это количество байтов, которое вы хотите записать за раз. у обоих из них также нет условия для проверки того, что является бонусом.
Да, но я подумал, что, возможно, это будет легче понять, потому что он копирует целые строки, а не их части (на случай, если мы не знаем, сколько байтов в каждой строке).
Совершенно верно. Кодирование для обучения и кодирование для повышения эффективности очень разные.
@owns Чтобы добавить к этому вопросу год спустя, writelines() показал немного лучшую производительность по сравнению с write(), поскольку мы не тратим время на постоянное открытие нового файлового потока, а вместо этого записываем новые строки как один большой поток байтов.
глядя на источник - Writelines вызывает write, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio. c. Кроме того, файловый поток уже открыт, поэтому записи не нужно будет открывать его каждый раз заново.
Это ужасно. Он выполняет ненужную работу без уважительной причины. Это не работает для произвольных файлов. Копия не идентична байтам, если входные данные имеют необычные окончания строк в таких системах, как Windows. Как вы думаете, почему это проще понять, чем вызов функции копирования в shutil? Даже при игнорировании shutil простой цикл блочного чтения / записи (с использованием небуферизованного ввода-вывода) будет прямым, будет эффективным и будет иметь гораздо больше смысла, чем этот, и, следовательно, его, безусловно, легче научить и понять.
Это также увеличивает накладные расходы на декодирование / кодирование и не работает с двоичными данными. Просто используйте shutil.copyfile(), который в 3.8 был дополнительно улучшен, чтобы использовать встроенную поддержку ОС для быстрого копирования файлов. Это легко займет меньше половины времени от того, что займет этот ответ.
from subprocess import call
call("cp -p <file> <file>", shell=True)
Это зависит от платформы, поэтому я бы не стал его использовать.
Такой call небезопасен. Пожалуйста, обратитесь к документу подпроцесса об этом.
это не переносимо и не нужно, так как вы можете просто использовать shutil.
Хм, а почему тогда Python?
Возможно, обнаружите операционную систему перед запуском (будь то DOS или Unix, потому что они наиболее часто используются)
Вы можете использовать одну из функций копирования из пакета shutil:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Function preserves supports accepts copies other
permissions directory dest. file obj metadata
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
shutil.copy ✔ ✔ ☐ ☐
shutil.copy2 ✔ ✔ ☐ ✔
shutil.copyfile ☐ ☐ ☐ ☐
shutil.copyfileobj ☐ ☐ ✔ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Пример:
import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')
Просто любопытно, как вы создали эту таблицу?
@lightalchemist Я просто использовал vim в качестве блокнота, скопировал использованные символы Unicode из таблицы википедии и скопировал результат в редактор stackoverflow для окончательной полировки.
Чем это отличается от другого ответа двумя годами ранее? stackoverflow.com/a/30359308/674039
@wim, вы должны сравнить мой ответ с Версия ответа, который вы связали, 2017 г., которое было текущим, когда я опубликовал свой ответ. Основные отличия: в моем ответе используются более качественные / описательные заголовки столбцов, макет таблицы не отвлекает, он включает прямые ссылки на документацию, и я добавил столбец (т.е. «принимает файл obj»).
В ПОРЯДКЕ. YMMV, но я думаю, что косметические изменения и подобные мелкие улучшения лучше вносить в существующие ответы, а не дублировать их.
@wim проверьте ссылку, которую я опубликовал, это было бы довольно существенным изменением существующего ответа.
shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
@gman 'shutil фактически не копирует файлы' - это очень вводящее в заблуждение утверждение - предупреждение, на которое вы ссылаетесь, касается метаданных. В зависимости от вашего варианта использования вы действительно или явно не хотите копировать определенные виды метаданных. Конечно, с обычными привилегиями пользователя информация о владельце пользователя / группы часто легко теряется из-за недостаточных привилегий! С этим ничего не может поделать функция копирования высокого уровня!
Заблуждение состоит в том, что эти функции копируют файлы. Они этого не делают. Они читают файл и записывают новый. Доказательство. Попытка копирования с cp на Mac или copy на Windows. Повторите эти действия с этими функциями. Эти функции не дают одинакового результата. Данные теряются, большая часть из них - важные данные. В качестве встречного примера функция C# Copy фактически копирует файлы, по крайней мере, на Mac и Windows. Node также копирует в Windows (ошибка на Mac). Пример: controlc.com/f3e3b9f7
Для небольших файлов и использования только встроенных модулей Python вы можете использовать следующий однострочный файл:
with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())
Как @maxschlepzig упомянул в комментариях ниже, это не оптимальный способ для приложений, где файл слишком велик или когда память критична, поэтому следует отдавать предпочтение ответу Свати.
Это считывает полный исходный файл в память перед его обратной записью. Таким образом, это излишне тратит память на все операции копирования файлов, кроме самых мелких.
Это правда? Я думаю, что .read() и .write() по умолчанию буферизированы (по крайней мере, для CPython).
@soundstripe, конечно это правда. Тот факт, что объект файла, возвращаемый open(), выполняет буферизованный ввод-вывод, по умолчанию вам здесь не поможет, потому что read() указан как: «Если n отрицательное или опущено, читать до EOF». Это означает, что read() возвращает полное содержимое файла в виде строки.
@maxschlepzig Я понимаю вашу точку зрения и признаю, что не знал об этом. Причина, по которой я дал этот ответ, заключалась в том, что кто-то хотел сделать простую копию файла, используя только встроенные модули, без необходимости импортировать для него модуль. Конечно, оптимизация памяти не должна вызывать беспокойства, если вам нужна эта опция. В любом случае, спасибо, что прояснили это. Я обновил ответ соответственно.
Во-первых, я сделал для вас исчерпывающий перечень методов shutil.
shutil_methods =
{'copy':['shutil.copyfileobj',
'shutil.copyfile',
'shutil.copymode',
'shutil.copystat',
'shutil.copy',
'shutil.copy2',
'shutil.copytree',],
'move':['shutil.rmtree',
'shutil.move',],
'exception': ['exception shutil.SameFileError',
'exception shutil.Error'],
'others':['shutil.disk_usage',
'shutil.chown',
'shutil.which',
'shutil.ignore_patterns',]
}
Во-вторых, объясните методы копирования в примерах:
shutil.copyfileobj(fsrc, fdst[, length])manipulate opened objects
In [3]: src = '~/Documents/Head+First+SQL.pdf'
In [4]: dst = '~/desktop'
In [5]: shutil.copyfileobj(src, dst)
AttributeError: 'str' object has no attribute 'read'
#copy the file object
In [7]: with open(src, 'rb') as f1,open(os.path.join(dst,'test.pdf'), 'wb') as f2:
...: shutil.copyfileobj(f1, f2)
In [8]: os.stat(os.path.join(dst,'test.pdf'))
Out[8]: os.stat_result(st_mode=33188, st_ino=8598319475, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067347, st_mtime=1516067335, st_ctime=1516067345)
shutil.copyfile(src, dst, *, follow_symlinks=True)Copy and rename
In [9]: shutil.copyfile(src, dst)
IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
#so dst should be a filename instead of a directory name
shutil.copy()Copy without preseving the metadata
In [10]: shutil.copy(src, dst)
Out[10]: ~/desktop/Head+First+SQL.pdf'
#check their metadata
In [25]: os.stat(src)
Out[25]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066425, st_mtime=1493698739, st_ctime=1514871215)
In [26]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[26]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066427, st_mtime=1516066425, st_ctime=1516066425)
# st_atime,st_mtime,st_ctime changed
shutil.copy2()Copy with preseving the metadata
In [30]: shutil.copy2(src, dst)
Out[30]: ~/desktop/Head+First+SQL.pdf'
In [31]: os.stat(src)
Out[31]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067055, st_mtime=1493698739, st_ctime=1514871215)
In [32]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[32]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067063, st_mtime=1493698739, st_ctime=1516067055)
# Preseved st_mtime
shutil.copytree()
Рекурсивно копировать все дерево каталогов с корнем src, возвращая целевой каталог
shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
В Python вы можете копировать файлы, используя
import os
import shutil
import subprocess
shutilshutil.copyfile(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copyfile('source.txt', 'destination.txt')
shutil.copy(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy('source.txt', 'destination.txt')
shutil.copy2(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy2('source.txt', 'destination.txt')
shutil.copyfileobj(src_file_object, dest_file_object[, length])
# example
file_src = 'source.txt'
f_src = open(file_src, 'rb')
file_dest = 'destination.txt'
f_dest = open(file_dest, 'wb')
shutil.copyfileobj(f_src, f_dest)
osos.popen(cmd[, mode[, bufsize]])
# example
# In Unix/Linux
os.popen('cp source.txt destination.txt')
# In Windows
os.popen('copy source.txt destination.txt')
os.system(command)
# In Linux/Unix
os.system('cp source.txt destination.txt')
# In Windows
os.system('copy source.txt destination.txt')
subprocesssubprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.call('cp source.txt destination.txt', shell=True)
# In Windows
status = subprocess.call('copy source.txt destination.txt', shell=True)
Подпись subprocess.check_output
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.check_output('cp source.txt destination.txt', shell=True)
# In Windows
status = subprocess.check_output('copy source.txt destination.txt', shell=True)
Использование однострочных команд является плохим стилем кодирования (гибкость, надежность и безопасность), вместо этого используйте синтаксис ['copy', sourcefile, destfile] везде, где это возможно, особенно если параметры вводятся пользователем.
Почему вы перечисляете так много плохих альтернатив функциям копирования shutil?
shutil встроен, нет необходимости предоставлять непереносимые альтернативы. На самом деле ответ можно улучшить, удалив системные решения, и после этого удаления этот ответ будет просто копией существующих ответов / копией документации.
os.popen на некоторое время устарел. и check_output возвращает не статус, а вывод (который пуст в случае copy/cp)
shutil на самом деле не копирует файлы. Есть большое жирное предупреждение прямо в верхней части документации. "это означает, что теряются владелец файла и группа, а также списки управления доступом. В Mac OS вилка ресурсов и другие метаданные не используются. Это означает, что ресурсы будут потеряны, а тип файла и коды создателя будут неправильными. В Windows владельцы файлов, списки управления доступом и альтернативные потоки данных не копируются ».
open(destination, 'wb').write(open(source, 'rb').read())
Откройте исходный файл в режиме чтения и запишите в целевой файл в режиме записи.
Идея хороша, и код красив, но правильная функция copy () может делать больше вещей, таких как копирование атрибутов (+ x бит) или, например, удаление уже скопированных байтов в случае обнаружения условия переполнения диска. .
Разве это не отсутствие .close() на всех open(...)?
Нет необходимости в .close (), поскольку мы НЕ СОХРАНЯЕМ объект указателя файла нигде (ни для файла src, ни для файла назначения).
AFAIK, это не определено, когда файлы действительно закрыты, @SundeepBorra. Использование with (как в примере выше) рекомендуется и не более сложно. Использование read() для необработанного файла приводит к считыванию всего файла в память, которая может быть слишком большой. Используйте стандартную функцию, например, из shutil, чтобы вам и всем, кто участвует в коде, не нужно было беспокоиться об особых случаях. docs.python.org/3/library/io.html#io.BufferedReader
Тот же подход к неоптимальному расходу памяти, что и ответ yellow01.
Начиная с Python 3.5, вы можете делать следующее для небольших файлов (например, текстовых файлов, маленьких jpeg):
from pathlib import Path
source = Path('../path/to/my/file.txt')
destination = Path('../path/where/i/want/to/store/it.txt')
destination.write_bytes(source.read_bytes())
write_bytes перезапишет все, что было в месте назначения
А затем кто-то использует код (случайно или целенаправленно) в большом файле ... Использование функций из shutil решает все особые случаи за вас и дает вам душевное спокойствие.
по крайней мере, он не повторяет одни и те же решения снова и снова.
Python предоставляет встроенные функции для простого копирования файлов с помощью утилит оболочки операционной системы.
Следующая команда используется для копирования файла
shutil.copy(src,dst)
Следующая команда используется для копирования файла с информацией о метаданных.
shutil.copystat(src,dst)
Вы должны запустить copy, затем copystat, чтобы сохранить метаданные файла. В Python 3.3+ copystat также копирует расширенные атрибуты.
Вот простой способ сделать это без какого-либо модуля. Он похож на этот ответ, но имеет то преимущество, что он также работает, если это большой файл, который не помещается в ОЗУ:
with open('sourcefile', 'rb') as f, open('destfile', 'wb') as g:
while True:
block = f.read(16*1024*1024) # work by blocks of 16 MB
if not block: # end of file
break
g.write(block)
Поскольку мы пишем новый файл, он не сохраняет время модификации и т. д.
Затем мы можем использовать для этого os.utime, если это необходимо.
Подобно принятому ответу, следующий блок кода может пригодиться, если вы также хотите создать любые (несуществующие) папки на пути к месту назначения.
from os import path, makedirs
from shutil import copyfile
makedirs(path.dirname(path.abspath(destination_path)), exist_ok=True)
copyfile(source_path, destination_path)
Как отмечается в принятых ответах, эти строки перезапишут любой файл, который существует по пути назначения, поэтому иногда может быть полезно также добавить: if not path.exists(destination_path): перед этим блоком кода.
На случай, если вы зашли так далеко. Ответ в том, что вам нужен полный путь и имя файла.
import os
shutil.copy(os.path.join(old_dir, file), os.path.join(new_dir, file))
В чем разница между копией и копией файла?