10.10. shutil — 高级的文件操作(复制、移动、删除、打包)

10.10. shutil — 高级文件操作

10.10.1. 目录与文件操作

shutil.copyfileobj(fsrcfdst[, length])

把文件对象(fsrc)读出来,存入另一个文件对象(fdst),可以自定义缓冲区长度(length)

import gzip
import shutil
with open('file.txt', 'rb') as f_in, gzip.open('file.txt.gz', 'wb') as f_out:
    shutil.copyfileobj(f_in, f_out)
shutil.copyfile(srcdst)

把文件(src)读出来,存入另一个文件(dst);

跟 shutil.copy() 的区别是,如果原文件和新文件名字是一样的,则copy()的dst可以是目录

目标端必须可写,不然触发IOError

如果DST已经存在,它将被取代。特殊的文件,如字符或块设备和管道不能复制。

shutil.copymode(srcdst)

连同权限信息(用户及用户组)一起从源文件拷贝到目标文件

shutil.copystat(srcdst)

连同权限位、最后访问时间、最后修改时间(不含用户及用户组)一起从源文件拷贝到目标文件(不拷贝文件内容)

shutil.copy(srcdst)

从源文件拷贝到目标文件或目录,如果是目录会创建跟源文件一样的文件名的文件

shutil.copy2(srcdst)

相当于项 shutil.copy() 再 copystat(). 类型系统命令 cp -p.

shutil.ignore_patterns(*patterns)

创建一个回调函数,可以被 copytree() ignore参数使用,例子在下面

shutil.copytree(srcdstsymlinks=Falseignore=None)

递归复制一个目录树从src到目标目录dst,必须不能已经存在; 他将被自动创建. 权限及时间相关的请使用 copystat(),单个文件复制用shutil.copy2().

如果symlinks是真,则会创建新的软连接

可以用 ignore_patterns() 创建一个根据忽略规则的对象供ignore使用

shutil.rmtree(path[, ignore_errors[, onerror]])

删除一个目录树; path必须是个目录(但不能是个软链接). 如果ignore_errors是真, 失败的删除操作将被忽略; 如果为假或省略,错误将被onerror处理,如果onerror是省略会抛异常

如果onerror要配置, 配置的函数必须可以接受三个参数: functionpath, and excinfo. 第一个参数, function,是一个引发异常的函数; 可可以是 os.path.islink()os.listdir()os.remove() or os.rmdir(). 第二个参数, path, 把路径传入函数. 第三个参数, excinfo, 是一个 sys.exc_info()返回的错误. onerror处理的错误将不会再被抓住

shutil.move(srcdst)

递归地移动文件或目录(SRC)到另一个位置(DST)

如果目标是一个已经存在的目录,那就SRC移动到DST下面, 如果目标已经存在但不是目录,它可以覆盖取决于操作系统

exception shutil.Error

收集copytree()操作的错误,参数是一个列表的三元组(srcname,dstname,例外)

10.10.1.1. copytree的例子:

 copytree() 源码:

def copytree(src, dst, symlinks=False, ignore=None):
    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 symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks, ignore)
            else:
                copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error as err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except WindowsError:
        # can't copy file access times on Windows
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)

使用过滤ignore_patterns() :

from shutil import copytree, ignore_patterns
copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))

配合logging记录日志:

from shutil import copytree
import logging

def _logpath(path, names):
    logging.info('Working in %s' % path)
    return []   # nothing will be ignored

copytree(source, destination, ignore=_logpath)

10.10.2. 打包操作

基于zipfiletarfile模块

shutil.make_archive(base_nameformat[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]])

创建一个包文件(eg. zip or tar) 并返回他的全路径

base_name 被创建文件的名称(包括路径,但不包括扩展名)

format 里面的其中一种格式“zip”, “tar”, “bztar” or “gztar”.

root_dir 被打包文件的根目录,默认会进入到此文件夹,把里面所有内容进行压缩

base_dir 从指定的目录开始打包

root_dir 和 base_dir 都默认是当前目录

owner and group are used when creating a tar archive. By default, uses the current owner and group.

logger must be an object compatible with PEP 282, usually an instance of logging.Logger.

shutil.get_archive_formats()

Return a list of supported formats for archiving. Each element of the returned sequence is a tuple (name, description).

By default shutil provides these formats:

  • gztar: gzip’ed tar-file
  • bztar: bzip2’ed tar-file
  • tar: uncompressed tar file
  • zip: ZIP file

You can register new formats or provide your own archiver for any existing formats, by using register_archive_format().

New in version 2.7.

shutil.register_archive_format(namefunction[, extra_args[, description]])

Register an archiver for the format namefunction is a callable that will be used to invoke the archiver.

If given, extra_args is a sequence of (name, value) that will be used as extra keywords arguments when the archiver callable is used.

description is used by get_archive_formats() which returns the list of archivers. Defaults to an empty list.

New in version 2.7.

shutil.unregister_archive_format(name)

Remove the archive format name from the list of supported formats.

New in version 2.7.

10.10.2.1. 打包示例

In this example, we create a gzip’ed tar-file archive containing all files found in the .ssh directory of the user:

>>>
>>> from shutil import make_archive
>>> import os
>>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
>>> root_dir = os.path.expanduser(os.path.join('~', '.ssh'))
>>> make_archive(archive_name, 'gztar', root_dir)
'/Users/tarek/myarchive.tar.gz'

The resulting archive contains:

$ tar -tzvf /Users/tarek/myarchive.tar.gz
drwx------ tarek/staff       0 2010-02-01 16:23:40 ./
-rw-r--r-- tarek/staff     609 2008-06-09 13:26:54 ./authorized_keys
-rwxr-xr-x tarek/staff      65 2008-06-09 13:26:54 ./config
-rwx------ tarek/staff     668 2008-06-09 13:26:54 ./id_dsa
-rwxr-xr-x tarek/staff     609 2008-06-09 13:26:54 ./id_dsa.pub
-rw------- tarek/staff    1675 2008-06-09 13:26:54 ./id_rsa
-rw-r--r-- tarek/staff     397 2008-06-09 13:26:54 ./id_rsa.pub
-rw-r--r-- tarek/staff   37192 2010-02-06 18:23:10 ./known_hosts
posted @ 2016-10-08 14:42  gold叠  阅读(790)  评论(0)    收藏  举报