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
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): 可能很有用。
Similar to the accepted answer, the following code block might come in handy if you also want to make sure to create any (non-existent) folders in the path to the destination.
from os import path, makedirs
from shutil import copyfile
makedirs(path.dirname(path.abspath(destination_path)), exist_ok=True)
copyfile(source_path, destination_path)
As the accepted answers notes, these lines will overwrite any file which exists at the destination path, so sometimes it might be useful to also add: if not path.exists(destination_path): before this code block.
def copyfileobj(fsrc, fdst, length=16*1024):
"""copy data from file-like object fsrc to file-like object fdst"""
while 1:
buf = fsrc.read(length)
if not buf:
break
fdst.write(buf)
For the answer everyone recommends, if you prefer not to use the standard modules, or have completely removed them as I've done, preferring more core C methods over poorly written python methods
The way shutil works is symlink/hardlink safe, but is rather slow due to os.path.normpath() containing a while (nt, mac) or for (posix) loop, used in testing if src and dst are the same in shutil.copyfile()
This part is mostly unneeded if you know for certain src and dst will never be the same file, otherwise a faster C approach could potentially be used.
(note that just because a module may be C doesn't inherently mean it's faster, know that what you use is actually written well before you use it)
After that initial testing, copyfile() runs a for loop on a dynamic tuple of (src, dst), testing for special files (such as sockets or devices in posix).
Finally, if follow_symlinks is False, copyfile() tests if src is a symlink with os.path.islink(), which varies between nt.lstat() or posix.lstat() (os.lstat()) on Windows and Linux, or Carbon.File.ResolveAliasFile(s, 0)[2] on Mac.
If that test resolves True, the core code that copies a symlink/hardlink is:
os.symlink(os.readlink(src), dst)
Hardlinks in posix are done with posix.link(), which shutil.copyfile() doesn't call, despite being callable through os.link().
(probably because the only way to check for hardlinks is to hashmap the os.lstat() (st_ino and st_dev specifically) of the first inode we know about, and assume that's the hardlink target)
Else, file copying is done via basic file buffers:
with open(src, 'rb') as fsrc:
with open(dst, 'wb') as fdst:
copyfileobj(fsrc, fdst)
(similar to other answers here)
copyfileobj() is a bit special in that it's buffer safe, using a length argument to read the file buffer in chunks:
def copyfileobj(fsrc, fdst, length=16*1024):
"""copy data from file-like object fsrc to file-like object fdst"""
while 1:
buf = fsrc.read(length)
if not buf:
break
fdst.write(buf)
Hope this answer helps shed some light on the mystery of file copying using core mechanisms in python. :)
Overall, shutil isn't too poorly written, especially after the second test in copyfile(), so it's not a horrible choice to use if you're lazy, but the initial tests will be a bit slow for a mass copy due to the minor bloat.
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)
Here is a simple way to do it, without any module. It's similar to this answer, but has the benefit to also work if it's a big file that doesn't fit in RAM:
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)
Since we're writing a new file, it does not preserve the modification time, etc.
We can then use os.utime for this if needed.
def copy(source, destination):
with open(source, 'rb') as file:
myFile = file.read()
with open(destination, 'wb') as file:
file.write(myFile)
copy("foo.txt", "bar.txt")
文件将打开,其数据将写入您选择的新文件中。
I would like to propose a different solution.
def copy(source, destination):
with open(source, 'rb') as file:
myFile = file.read()
with open(destination, 'wb') as file:
file.write(myFile)
copy("foo.txt", "bar.txt")
The file is opened, and it's data is written to a new file of your choosing.
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)
Copying a file is a relatively straightforward operation as shown by the examples below, but you should instead use the shutil stdlib module for that.
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)
If you want to copy by filename you could do something like this:
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)
Copy the contents of the file named src to a file named dst. The destination location must be writable; otherwise, an IOError exception will be raised. If dst already exists, it will be replaced. Special files such as character or block devices and pipes cannot be copied with this function. src and dst are path names given as strings.
Take a look at filesys for all the file and directory handling functions available in standard Python modules.
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')
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(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)
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')
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(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)
发布评论
评论(21)
首先,我制作了一份详尽的 shutil 方法备忘单,供您参考。
其次,通过例子解释copy的方法:
shutil.copyfileobj(fsrc, fdst[, length])
操作打开的对象shutil.copyfile(src, dst, *, follow_symlinks=True)
复制并重命名< /p>shutil.copy()
复制而不保留元数据shutil.copy2()
复制并保留元数据shutil.copytree()
递归复制以 src 为根的整个目录树,返回目标目录。
Firstly, I made an exhaustive cheat sheet of the shutil methods for your reference.
Secondly, explaining methods of copy in examples:
shutil.copyfileobj(fsrc, fdst[, length])
manipulate opened objectsshutil.copyfile(src, dst, *, follow_symlinks=True)
Copy and renameshutil.copy()
Copy without preseving the metadatashutil.copy2()
Copy with preserving the metadatashutil.copytree()
Recursively copy an entire directory tree rooted at src, returning the destination directory.
从 Python 3.5 开始,您可以对小型文件执行以下操作文件(即:文本文件、小 jpeg):
write_bytes
将覆盖目标位置的所有内容As of Python 3.5 you can do the following for small files (ie: text files, small jpegs):
write_bytes
will overwrite whatever was at the destination's location您可以使用 os.system('cp nameofile generatedbyprogram /otherdirectory/')。
或者正如我所做的那样,
其中
rawfile
是我在程序内生成的名称。这是仅限 Linux 的解决方案。
You could use
os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
.Or as I did it,
where
rawfile
is the name that I had generated inside the program.This is a Linux-only solution.
使用
以读模式打开源文件,以写模式写入目标文件。
Use
Open the source file in read mode, and write to the destination file in write mode.
使用
subprocess.call
复制文件Use
subprocess.call
to copy the file对于大文件,我逐行读取文件并将每一行读入一个数组。 然后,一旦数组达到一定大小,将其追加到新文件中。
For large files, I read the file line by line and read each line into an array. Then, once the array reached a certain size, append it to a new file.
万一你已经落到这一步了。 答案是你需要完整的路径和文件名
In case you've come this far down. The answer is that you need the entire path and file name
与接受的答案类似,如果您还想确保在目标路径中创建任何(不存在的)文件夹,则以下代码块可能会派上用场。
正如接受的答案所指出的,这些行将覆盖目标路径中存在的任何文件,因此有时在此代码块之前添加:
if not path.exists(destination_path):
可能很有用。Similar to the accepted answer, the following code block might come in handy if you also want to make sure to create any (non-existent) folders in the path to the destination.
As the accepted answers notes, these lines will overwrite any file which exists at the destination path, so sometimes it might be useful to also add:
if not path.exists(destination_path):
before this code block.对于每个人都推荐的答案,如果您不想使用标准模块,或者像我一样完全删除它们,则更喜欢更多核心 C 方法而不是写得不好的 python 方法
Shutil 的工作方式是符号链接/硬链接安全的,但更安全由于 os.path.normpath() 包含 while (nt, mac) 或 for (posix) 循环,用于测试 if src 和 dst<,因此速度较慢/code> 与
shutil.copyfile()
中的相同如果您知道某些
src
和dst
会,则这部分基本上是不需要的永远不要是同一个文件,否则可能会使用更快的 C 方法。(请注意,仅仅因为模块可能是 C 语言并不意味着它本身就更快,请在使用之前知道您使用的内容实际上是写好的)
在初始测试之后,
copyfile()
在(src, dst)
动态元组上运行 for 循环,测试特殊文件(例如 posix 中的套接字或设备)。最后,如果
follow_symlinks
为 False,则copyfile()
使用os.path.islink()
测试src
是否为符号链接code>,在 Windows 和 Linux 上,它在nt.lstat()
或posix.lstat()
(os.lstat()
) 之间变化,或 Mac 上的Carbon.File.ResolveAliasFile(s, 0)[2]
。如果该测试解析为 True,则复制符号链接/硬链接的核心代码为:
posix 中的硬链接是通过 posix.link() 完成的,而
shutil.copyfile() 则不这样做不调用,尽管可以通过 os.link() 调用。
(可能是因为检查硬链接的唯一方法是对第一个 inode 的 os.lstat() 进行哈希映射(特别是 st_ino 和 st_dev)我们知道,并假设这是硬链接目标)
否则,文件复制是通过基本文件缓冲区完成的:(
与此处的其他答案类似)
copyfileobj()
有点特殊,因为它是缓冲区安全的,使用alength
参数以块的形式读取文件缓冲区:希望这个答案有助于揭示使用 python 中的核心机制进行文件复制的奥秘。 :)
总的来说,shutil 写得还不错,尤其是在
copyfile()
中进行第二次测试之后,所以如果你很懒的话,使用它并不是一个可怕的选择,但最初的测试将是一个由于轻微的膨胀,批量复制有点慢。For the answer everyone recommends, if you prefer not to use the standard modules, or have completely removed them as I've done, preferring more core C methods over poorly written python methods
The way shutil works is symlink/hardlink safe, but is rather slow due to
os.path.normpath()
containing a while (nt, mac) or for (posix) loop, used in testing ifsrc
anddst
are the same inshutil.copyfile()
This part is mostly unneeded if you know for certain
src
anddst
will never be the same file, otherwise a faster C approach could potentially be used.(note that just because a module may be C doesn't inherently mean it's faster, know that what you use is actually written well before you use it)
After that initial testing,
copyfile()
runs a for loop on a dynamic tuple of(src, dst)
, testing for special files (such as sockets or devices in posix).Finally, if
follow_symlinks
is False,copyfile()
tests ifsrc
is a symlink withos.path.islink()
, which varies betweennt.lstat()
orposix.lstat()
(os.lstat()
) on Windows and Linux, orCarbon.File.ResolveAliasFile(s, 0)[2]
on Mac.If that test resolves True, the core code that copies a symlink/hardlink is:
Hardlinks in posix are done with
posix.link()
, whichshutil.copyfile()
doesn't call, despite being callable throughos.link()
.(probably because the only way to check for hardlinks is to hashmap the
os.lstat()
(st_ino
andst_dev
specifically) of the first inode we know about, and assume that's the hardlink target)Else, file copying is done via basic file buffers:
(similar to other answers here)
copyfileobj()
is a bit special in that it's buffer safe, using alength
argument to read the file buffer in chunks:Hope this answer helps shed some light on the mystery of file copying using core mechanisms in python. :)
Overall, shutil isn't too poorly written, especially after the second test in
copyfile()
, so it's not a horrible choice to use if you're lazy, but the initial tests will be a bit slow for a mass copy due to the minor bloat.这是一种简单的方法,无需任何模块。 它类似于这个答案,但有如果它是一个不适合 RAM 的大文件,这样做的好处是:
由于我们正在编写一个新文件,因此它不会保留修改时间等。
然后我们可以使用
os.utime
如果需要的话。Here is a simple way to do it, without any module. It's similar to this answer, but has the benefit to also work if it's a big file that doesn't fit in RAM:
Since we're writing a new file, it does not preserve the modification time, etc.
We can then use
os.utime
for this if needed.我想提出一个不同的解决方案。
文件将打开,其数据将写入您选择的新文件中。
I would like to propose a different solution.
The file is opened, and it's data is written to a new file of your choosing.
复制文件是一个相对简单的操作,如下面的示例所示,但您应该使用 shutil stdlib模块为此。
如果你想按文件名复制,你可以这样做:
Copying a file is a relatively straightforward operation as shown by the examples below, but you should instead use the shutil stdlib module for that.
If you want to copy by filename you could do something like this:
使用 shutil 模块。
将名为 src 的文件的内容复制到名为 dst 的文件中。 目标位置必须可写; 否则,将引发 IOError 异常。 如果dst已经存在,它将被替换。 特殊文件(例如字符或块设备和管道)无法使用此功能复制。 src 和 dst 是以字符串形式给出的路径名。
查看 filesys 了解标准 Python 中可用的所有文件和目录处理函数模块。
Use the shutil module.
Copy the contents of the file named src to a file named dst. The destination location must be writable; otherwise, an IOError exception will be raised. If dst already exists, it will be replaced. Special files such as character or block devices and pipes cannot be copied with this function. src and dst are path names given as strings.
Take a look at filesys for all the file and directory handling functions available in standard Python modules.
目录和文件复制示例,来自 Tim Golden 的 Python Stuff em>:
Directory and File copy example, from Tim Golden's Python Stuff:
对于小文件并且仅使用 Python 内置函数,您可以使用以下一行:
对于文件太大或内存至关重要的应用程序,这不是最佳方式,因此 Swati的答案应该是首选。
For small files and using only Python built-ins, you can use the following one-liner:
This is not optimal way for applications where the file is too large or when memory is critical, thus Swati's answer should be preferred.
在 Python 中复制文件有两种最佳方法。
1.我们可以使用
shutil
模块代码示例:
除了copyfile之外,还有其他方法可用,例如copy、copy2等,但copyfile在性能方面是最好的,
2.我们可以使用
OS
模块代码示例:
另一种方法是使用subprocess,但它不是优选的,因为它是调用方法之一并且不安全。
There are two best ways to copy file in Python.
1. We can use the
shutil
moduleCode Example:
There are other methods available also other than copyfile, like copy, copy2, etc, but copyfile is best in terms of performance,
2. We can use the
OS
moduleCode Example:
Another method is by the use of a subprocess, but it is not preferable as it’s one of the call methods and is not secure.
复制文件
shutil
< /a> 模块os
模块子进程
模块1) 使用
shutil
模块shutil.copyfile
< /a> 签名shutil.copy
签名<代码>shutil.copy2签名
shutil.copyfileobj
签名2) 使用
os
模块os.popen
签名os.system
签名3) 使用
subprocess
模块subprocess.call
签名subprocess.check_output
签名In Python, you can copy the files using
shutil
moduleos
modulesubprocess
module1) Copying files using
shutil
moduleshutil.copyfile
signatureshutil.copy
signatureshutil.copy2
signatureshutil.copyfileobj
signature2) Copying files using
os
moduleos.popen
signatureos.system
signature3) Copying files using
subprocess
modulesubprocess.call
signaturesubprocess.check_output
signature您可以使用
shutil
封装:示例:
You can use one of the copy functions from the
shutil
package:Example:
shutil
有许多可以使用的方法。 其中之一是:src
的文件的内容复制到名为dst
的文件。src
和dst
都需要是文件的完整文件名,包括路径。IOError
异常。dst
已经存在,它将被替换。copy
,src
和dst
是以str
形式给出的路径名。另一个值得关注的
shutil
方法是Shutil.copy2()
。 它类似,但保留更多元数据(例如时间戳)。如果您使用
os.path
操作,请使用copy
而不是copyfile
。copyfile
只接受字符串。shutil
has many methods you can use. One of which is:src
to a file nameddst
. Bothsrc
anddst
need to be the entire filename of the files, including path.IOError
exception will be raised.dst
already exists, it will be replaced.copy
,src
anddst
are path names given asstr
s.Another
shutil
method to look at isshutil.copy2()
. It's similar but preserves more metadata (e.g. time stamps).If you use
os.path
operations, usecopy
rather thancopyfile
.copyfile
will only accept strings.元数据
权限
可以是目录
metadata
permissions
may be directory
copy2(src,dst)
通常比copyfile(src,dst)
因为:dst
成为目录(而不是完整的目标文件名),在这种情况下 basename ofsrc
用于创建新文件;这是一个简短的例子:
copy2(src,dst)
is often more useful thancopyfile(src,dst)
because:dst
to be a directory (instead of the complete target filename), in which case the basename ofsrc
is used for creating the new file;Here is a short example: