Python中shutil模块的常用文件操作函数用法示例
|
os模块提供了对目录或者文件的新建/删除/查看文件属性,还提供了对文件以及目录的路径操作。比如说:绝对路径,父目录…… 但是,os文件的操作还应该包含移动 复制 打包 压缩 解压等操作,这些os模块都没有提供。
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)
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)
def copymode(src,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 "<stdin>",line 1,in <module>
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,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,_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,follow_symlinks=follow)
def copy(src,follow_symlinks=True):
if os.path.isdir(dst):
dst = os.path.join(dst,os.path.basename(src))
copyfile(src,follow_symlinks=follow_symlinks)
copymode(src,follow_symlinks=follow_symlinks)
return dst
def copy2(src,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,follow_symlinks=follow_symlinks)
copystat(src,follow_symlinks=follow_symlinks)
return dst
def copytree(src,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,symlinks,ignore,copy_function)
else:
copy_function(srcname,dstname)
elif os.path.isdir(srcname):
copytree(srcname,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,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,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
def rmtree(path,onerror=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,sys.exc_info())
return
try:
if os.path.samestat(orig_st,os.fstat(fd)):
_rmtree_safe_fd(fd,onerror)
try:
os.rmdir(path)
except OSError:
onerror(os.rmdir,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,sys.exc_info())
finally:
os.close(fd)
else:
return _rmtree_unsafe(path,onerror)
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
压缩打包
def make_archive(base_name,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
>>> 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
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
