Відповіді:
shutil
є багато методів, якими ви можете скористатися. Один з яких:
from shutil import copyfile
copyfile(src, dst)
Якщо ви використовуєте os.path
операції, copy
скоріше використовуйте copyfile
. copyfile
буде приймати тільки рядок .
~
, але він може мати відносні шляхи
┌──────────────────┬────────┬───────────┬───────┬────────────────┐
│ Function │ Copies │ Copies │Can use│ Destination │
│ │metadata│permissions│buffer │may be directory│
├──────────────────┼────────┼───────────┼───────┼────────────────┤
│shutil.copy │ No │ Yes │ No │ Yes │
│shutil.copyfile │ No │ No │ No │ No │
│shutil.copy2 │ Yes │ Yes │ No │ Yes │
│shutil.copyfileobj│ No │ No │ Yes │ No │
└──────────────────┴────────┴───────────┴───────┴────────────────┘
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
copyfile
значно швидше, ніжcopy2
shutil.copy2('/dir/file.ext', '/new/dir/')
(з косою рискою за цільовим контуром) усуне неоднозначність щодо того, чи потрібно копіювати в новий файл під назвою "dir", або вставити файл у каталог з таким ім'ям?
/new/dir
це вже існуючий каталог, дивіться коментар @ MatthewAlpert.
/new/dir/
його не існує, Python викине IsADirectoryError
файл, інакше він копіює файл /new/dir/
під оригінальним іменем.
Ви можете використовувати одну з функцій копіювання з shutil
пакета:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Функція зберігає підтримку, приймає копії інших довідник дозволів dest. метадані файлу obj ―――――――――――――――――――――――――――――――――――――――――――――――――― ―――――――――――――――――――――――――――― shutil.copy ✔ ✔ ☐ ☐ shutil.copy2 ✔ ✔ ☐ ✔ shutil.copyfile ☐ ☐ ☐ ☐ shutil.copyfileobj ☐ ☐ ✔ ☐ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Приклад:
import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')
У Python ви можете скопіювати файли за допомогою
shutil
модульos
модульsubprocess
модульimport os
import shutil
import subprocess
shutil
модуляshutil.copyfile
підпис
shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copyfile('source.txt', 'destination.txt')
shutil.copy
підпис
shutil.copy(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy('source.txt', 'destination.txt')
shutil.copy2
підпис
shutil.copy2(src_file, dest_file, *, follow_symlinks=True)
# example
shutil.copy2('source.txt', 'destination.txt')
shutil.copyfileobj
підпис
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)
os
модуляos.popen
підпис
os.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
підпис
os.system(command)
# In Linux/Unix
os.system('cp source.txt destination.txt')
# In Windows
os.system('copy source.txt destination.txt')
subprocess
модуляsubprocess.call
підпис
subprocess.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]
синтаксис, де це можливо, особливо якщо параметри надходять з користувальницьких даних.
os.popen
на деякий час застаріла. і check_output
не повертає статус, але вихід (який у випадку порожній copy/cp
)
Копіювання файлу є відносно простою операцією, як показано на прикладах нижче, але замість цього слід використовувати модуль 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.copyfileobj
. Крім того, у вас немає жодних try, finally
можливостей обробляти закриття файлів після винятку. Однак я б сказав, що ваша функція взагалі не повинна відповідати за відкриття та закриття файлів. Це має виконувати функцію обгортки, як, наприклад, як shutil.copyfile
обгортання shutil.copyfileobj
.
dest
що підлягає запису:open(dest, 'wb')
Використовуйте шутильний модуль .
copyfile(src, dst)
Скопіюйте вміст файла з ім'ям src у файл з назвою dst. Місце призначення повинно бути записаним; інакше буде піднято виняток IOError. Якщо dst вже існує, його буде замінено. Спеціальні файли, такі як символьні або блокові пристрої та труби, не можна скопіювати за допомогою цієї функції. src і dst - це назви шляхів, задані у вигляді рядків.
Ознайомтеся з файлами файлів для всіх функцій обробки файлів і каталогів, доступних у стандартних модулях Python.
Приклад копіювання каталогів та файлів - із матеріалу Python Tim Tim Golden:
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"
По-перше, я зробив вичерпний чіт-лист шутильних методів для вашої довідки.
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])
маніпулювати відкритими предметами
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)
Скопіюйте та перейменуйте
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()
Скопіюйте без попереднього встановлення метаданих
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()
Скопіюйте за допомогою попереднього налаштування метаданих
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, повертаючи каталог призначення
Для невеликих файлів та використання лише вбудованих файлів python ви можете використовувати наступний однокласник:
with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())
Як @maxschlepzig згадується в коментарях нижче, це не оптимальний спосіб для додатків, де файл занадто великий або коли пам'ять критична, тому відповіді Сваті слід віддавати перевагу.
.read()
і .write()
вони буферизовані за замовчуванням (принаймні для CPython).
open()
буферизованим IO, за замовчуванням не допомагає вам тут, тому що read()
вказано як: "Якщо n від'ємне чи пропущене, читайте до EOF." Це означає, що read()
повертає весь вміст файлу у вигляді рядка.
Ви можете використовувати os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
або як я це зробив,
os.system('cp '+ rawfile + ' rawdata.dat')
де rawfile
назва, яку я створив всередині програми.
Це єдине рішення для Linux
shutil
це недоступно - краща альтернатива - subprocess.run()
(без shell=True
!) os.system()
.
subprocess.run()
як запропонував @maxschlepzig - це великий крок вперед під час виклику зовнішніх програм. Для гнучкості та безпеки використовуйте ['cp', rawfile, 'rawdata.dat']
форму передачі командного рядка. (Однак для копіювання shutil
друзям рекомендується дзвонити до зовнішньої програми.)
Для великих файлів я читав файл за рядком і читав кожен рядок у масиві. Потім, як тільки масив досяг певного розміру, додайте його до нового файлу.
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
кількість байтів, які ви хотіли б написати за один раз. вони також не мають умови перевірити, що є бонусом.
shutil
? Навіть при ігноруванні shutil
простий блок циклу читання / запису (використовуючи нерозподілений IO) прямо вперед, був би ефективним і мав би набагато більше сенсу, ніж це, і, таким чином, напевно легше навчати та розуміти.
from subprocess import call
call("cp -p <file> <file>", shell=True)
call
є незахищеним. Будь ласка, ознайомтесь із документацією щодо цього підпроцесу.
З Python 3.5 ви можете зробити наступне для невеликих файлів (тобто: текстові файли, невеликі jpegs):
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
обробки всіх особливих випадків для вас і дає вам спокій.
open(destination, 'wb').write(open(source, 'rb').read())
Відкрийте вихідний файл у режимі читання та запишіть у цільовий файл у режимі запису.
.close()
на всіх цих open(...)
s?
Python пропонує вбудовані функції для легкого копіювання файлів за допомогою утилітів оболонки операційної системи.
Наступна команда використовується для копіювання файлу
shutil.copy(src,dst)
Наступна команда використовується для копіювання файлу з інформацією про метадані
shutil.copystat(src,dst)
copy
Потім слід запустити, copystat
щоб зберегти метадані файлів. У Python 3.3+ copystat
також копіюються розширені атрибути.