python中shutil.copyfile的用法_Python中shutil模块的常用文件操作函数用法示例

os模块提供了对目录或者文件的新建/删除/查看文件属性,还提供了对文件以及目录的路径操作。比如说:绝对路径,父目录…… 但是,os文件的操作还应该包含移动 复制 打包 压缩 解压等操作,这些os模块都没有提供。

而本文所讲的shutil则就是对os中文件操作的补充。--移动 复制 打包 压缩 解压,

shutil函数功能:

1 shutil.copyfileobj(fsrc, fdst[, length=16*1024])copy文件内容到另一个文件,可以copy指定大小的内容

先来看看其源代码。

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)

注意! 在其中fsrc,fdst都是文件对象,都需要打开后才能进行复制操作

import shutil

f1=open('name','r')

f2=open('name_copy','w+')

shutil.copyfileobj(f1,f2,length=16*1024)

2 shutil.copyfile(src,dst)copy文件内容,是不是感觉上面的文件复制很麻烦?还需要自己手动用open函数打开文件,在这里就不需要了,事实上,copyfile调用了copyfileobj

def copyfile(src, dst, *, follow_symlinks=True):

if _samefile(src, dst):

raise SameFileError("{!r} and {!r} are the same file".format(src, dst))

for fn in [src, dst]:

try:

st = os.stat(fn)

except OSError:

# File most likely does not exist

pass

else:

# XXX What about other special files? (sockets, devices...)

if stat.S_ISFIFO(st.st_mode):

raise SpecialFileError("`%s` is a named pipe" % fn)

if not follow_symlinks and os.path.islink(src):

os.symlink(os.readlink(src), dst)

else:

with open(src, 'rb') as fsrc:

with open(dst, 'wb') as fdst:

copyfileobj(fsrc, fdst)

return dst

shutil.copyfile('name','name_copy_2')

#一句就可以实现复制文件内容

3 shutil.copymode(src,dst)仅copy权限,不更改文件内容,组和用户。

def copymode(src, dst, *, follow_symlinks=True):

if not follow_symlinks and os.path.islink(src) and os.path.islink(dst):

if hasattr(os, 'lchmod'):

stat_func, chmod_func = os.lstat, os.lchmod

else:

return

elif hasattr(os, 'chmod'):

stat_func, chmod_func = os.stat, os.chmod

else:

return

st = stat_func(src)

chmod_func(dst, stat.S_IMODE(st.st_mode))

先看两个文件的权限

[root@slyoyo python_test]# ls -l

total 4

-rw-r--r--. 1 root root 79 May 14 05:17 test1

-rwxr-xr-x. 1 root root 0 May 14 19:10 test2

运行命令

>>> import shutil

>>> shutil.copymode('test1','test2')

查看结果

[root@slyoyo python_test]# ls -l

total 4

-rw-r--r--. 1 root root 79 May 14 05:17 test1

-rw-r--r--. 1 root root 0 May 14 19:10 test2

当我们将目标文件换为一个不存在的文件时报错

>>> shutil.copymode('test1','test3')

Traceback (most recent call last):

File "", line 1, in

File "/usr/local/python/lib/python3.4/shutil.py", line 132, in copymode

chmod_func(dst, stat.S_IMODE(st.st_mode))

FileNotFoundError: [Errno 2] No such file or directory: 'test233'

4 shutil.copystat(src,dst)复制所有的状态信息,包括权限,组,用户,时间等

def copystat(src, dst, *, follow_symlinks=True):

def _nop(*args, ns=None, follow_symlinks=None):

pass

# follow symlinks (aka don't not follow symlinks)

follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst))

if follow:

# use the real function if it exists

def lookup(name):

return getattr(os, name, _nop)

else:

# use the real function only if it exists

# *and* it supports follow_symlinks

def lookup(name):

fn = getattr(os, name, _nop)

if fn in os.supports_follow_symlinks:

return fn

return _nop

st = lookup("stat")(src, follow_symlinks=follow)

mode = stat.S_IMODE(st.st_mode)

lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns),

follow_symlinks=follow)

try:

lookup("chmod")(dst, mode, follow_symlinks=follow)

except NotImplementedError:

# if we got a NotImplementedError, it's because

# * follow_symlinks=False,

# * lchown() is unavailable, and

# * either

# * fchownat() is unavailable or

# * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW.

# (it returned ENOSUP.)

# therefore we're out of options--we simply cannot chown the

# symlink. give up, suppress the error.

# (which is what shutil always did in this circumstance.)

pass

if hasattr(st, 'st_flags'):

try:

lookup("chflags")(dst, st.st_flags, follow_symlinks=follow)

except OSError as why:

for err in 'EOPNOTSUPP', 'ENOTSUP':

if hasattr(errno, err) and why.errno == getattr(errno, err):

break

else:

raise

_copyxattr(src, dst, follow_symlinks=follow)

5 shutil.copy(src,dst)复制文件的内容以及权限,先copyfile后copymode

def copy(src, dst, *, follow_symlinks=True):

if os.path.isdir(dst):

dst = os.path.join(dst, os.path.basename(src))

copyfile(src, dst, follow_symlinks=follow_symlinks)

copymode(src, dst, follow_symlinks=follow_symlinks)

return dst

6 shutil.copy2(src,dst)复制文件的内容以及文件的所有状态信息。先copyfile后copystat

def copy2(src, dst, *, follow_symlinks=True):

"""Copy data and all stat info ("cp -p src dst"). Return the file's

destination."

The destination may be a directory.

If follow_symlinks is false, symlinks won't be followed. This

resembles GNU's "cp -P src dst".

"""

if os.path.isdir(dst):

dst = os.path.join(dst, os.path.basename(src))

copyfile(src, dst, follow_symlinks=follow_symlinks)

copystat(src, dst, follow_symlinks=follow_symlinks)

return dst

7 shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,ignore_dangling_symlinks=False)

递归的复制文件内容及状态信息

def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,

ignore_dangling_symlinks=False):

names = os.listdir(src)

if ignore is not None:

ignored_names = ignore(src, names)

else:

ignored_names = set()

os.makedirs(dst)

errors = []

for name in names:

if name in ignored_names:

continue

srcname = os.path.join(src, name)

dstname = os.path.join(dst, name)

try:

if os.path.islink(srcname):

linkto = os.readlink(srcname)

if symlinks:

# We can't just leave it to `copy_function` because legacy

# code with a custom `copy_function` may rely on copytree

# doing the right thing.

os.symlink(linkto, dstname)

copystat(srcname, dstname, follow_symlinks=not symlinks)

else:

# ignore dangling symlink if the flag is on

if not os.path.exists(linkto) and ignore_dangling_symlinks:

continue

# otherwise let the copy occurs. copy2 will raise an error

if os.path.isdir(srcname):

copytree(srcname, dstname, symlinks, ignore,

copy_function)

else:

copy_function(srcname, dstname)

elif os.path.isdir(srcname):

copytree(srcname, dstname, symlinks, ignore, copy_function)

else:

# Will raise a SpecialFileError for unsupported file types

copy_function(srcname, dstname)

# catch the Error from the recursive copytree so that we can

# continue with other files

except Error as err:

errors.extend(err.args[0])

except OSError as why:

errors.append((srcname, dstname, str(why)))

try:

copystat(src, dst)

except OSError as why:

# Copying file access times may fail on Windows

if getattr(why, 'winerror', None) is None:

errors.append((src, dst, str(why)))

if errors:

raise Error(errors)

return dst

# version vulnerable to race conditions

[root@slyoyo python_test]# tree copytree_test/

copytree_test/

└── test

├── test1

├── test2

└── hahaha

[root@slyoyo test]# ls -l

total 0

-rw-r--r--. 1 python python 0 May 14 19:36 hahaha

-rw-r--r--. 1 python python 0 May 14 19:36 test1

-rw-r--r--. 1 root root 0 May 14 19:36 test2

>>> shutil.copytree('copytree_test','copytree_copy')

'copytree_copy'

[root@slyoyo python_test]# ls -l

total 12

drwxr-xr-x. 3 root root 4096 May 14 19:36 copytree_copy

drwxr-xr-x. 3 root root 4096 May 14 19:36 copytree_test

-rw-r--r--. 1 python python 79 May 14 05:17 test1

-rw-r--r--. 1 root root 0 May 14 19:10 test2

[root@slyoyo python_test]# tree copytree_copy/

copytree_copy/

└── test

├── hahaha

├── test1

└── test2

8 shutil.rmtree(path, ignore_errors=False, οnerrοr=None)递归地删除文件

def rmtree(path, ignore_errors=False, οnerrοr=None):

if ignore_errors:

def onerror(*args):

pass

elif onerror is None:

def onerror(*args):

raise

if _use_fd_functions:

# While the unsafe rmtree works fine on bytes, the fd based does not.

if isinstance(path, bytes):

path = os.fsdecode(path)

# Note: To guard against symlink races, we use the standard

# lstat()/open()/fstat() trick.

try:

orig_st = os.lstat(path)

except Exception:

onerror(os.lstat, path, sys.exc_info())

return

try:

fd = os.open(path, os.O_RDONLY)

except Exception:

onerror(os.lstat, path, sys.exc_info())

return

try:

if os.path.samestat(orig_st, os.fstat(fd)):

_rmtree_safe_fd(fd, path, onerror)

try:

os.rmdir(path)

except OSError:

onerror(os.rmdir, path, sys.exc_info())

else:

try:

# symlinks to directories are forbidden, see bug #1669

raise OSError("Cannot call rmtree on a symbolic link")

except OSError:

onerror(os.path.islink, path, sys.exc_info())

finally:

os.close(fd)

else:

return _rmtree_unsafe(path, onerror)

9 shutil.move(src, dst)递归的移动文件

def move(src, dst):

real_dst = dst

if os.path.isdir(dst):

if _samefile(src, dst):

# We might be on a case insensitive filesystem,

# perform the rename anyway.

os.rename(src, dst)

return

real_dst = os.path.join(dst, _basename(src))

if os.path.exists(real_dst):

raise Error("Destination path '%s' already exists" % real_dst)

try:

os.rename(src, real_dst)

except OSError:

if os.path.islink(src):

linkto = os.readlink(src)

os.symlink(linkto, real_dst)

os.unlink(src)

elif os.path.isdir(src):

if _destinsrc(src, dst):

raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))

copytree(src, real_dst, symlinks=True)

rmtree(src)

else:

copy2(src, real_dst)

os.unlink(src)

return real_dst

10 make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,dry_run=0, owner=None, group=None, logger=None)

压缩打包

def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,

dry_run=0, owner=None, group=None, logger=None):

save_cwd = os.getcwd()

if root_dir is not None:

if logger is not None:

logger.debug("changing into '%s'", root_dir)

base_name = os.path.abspath(base_name)

if not dry_run:

os.chdir(root_dir)

if base_dir is None:

base_dir = os.curdir

kwargs = {'dry_run': dry_run, 'logger': logger}

try:

format_info = _ARCHIVE_FORMATS[format]

except KeyError:

raise ValueError("unknown archive format '%s'" % format)

func = format_info[0]

for arg, val in format_info[1]:

kwargs[arg] = val

if format != 'zip':

kwargs['owner'] = owner

kwargs['group'] = group

try:

filename = func(base_name, base_dir, **kwargs)

finally:

if root_dir is not None:

if logger is not None:

logger.debug("changing back to '%s'", save_cwd)

os.chdir(save_cwd)

return filename

base_name: 压缩打包后的文件名或者路径名

format: 压缩或者打包格式 "zip", "tar", "bztar"or "gztar"

root_dir : 将哪个目录或者文件打包(也就是源文件)

>>> shutil.make_archive('tarball','gztar',root_dir='copytree_test')

[root@slyoyo python_test]# ls -l

total 12

drwxr-xr-x. 3 root root 4096 May 14 19:36 copytree_copy

drwxr-xr-x. 3 root root 4096 May 14 19:36 copytree_test

-rw-r--r--. 1 root root 0 May 14 21:12 tarball.tar.gz

-rw-r--r--. 1 python python 79 May 14 05:17 test1

-rw-r--r--. 1 root root 0 May 14 19:10 test2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值