Python shutil模块使用指南

Python shutil模块使用指南

目录

  1. 模块定位
  2. 核心功能分类
  3. 文件操作详解
  4. 目录操作大全
  5. 归档压缩处理
  6. 高级操作技巧
  7. 异常处理机制
  8. 性能优化策略
  9. 最佳实践
  10. 危险操作警示

1. 模块定位

shutil(shell utilities)是Python标准库中的高级文件操作模块:

  • 提供跨平台的文件/目录管理操作
  • 补充os模块的底层文件操作
  • 支持归档格式处理(zip/tar等)
  • 处理文件权限和元数据

典型应用场景:

import shutil
from pathlib import Path

# 项目部署操作示例
def deploy_project(source_dir: Path, dest_dir: Path):
    if dest_dir.exists():
        shutil.rmtree(dest_dir)
    shutil.copytree(source_dir, dest_dir)
    shutil.make_archive(str(dest_dir), 'zip', dest_dir)

2. 核心功能分类

功能矩阵表

类别主要函数
文件操作copyfile(), copy(), copy2(), move(), rmtree()
目录操作copytree(), disk_usage(), chown()
归档压缩make_archive(), unpack_archive(), register_archive_format()
权限管理copymode(), copystat(), ignore_patterns()
系统命令which(), get_terminal_size()

3. 文件操作详解

基础复制操作

# 元数据不复制(仅内容)
shutil.copyfile('src.txt', 'dst.txt')

# 复制文件+权限
shutil.copy('src.txt', 'dir/')

# 复制文件+所有元数据(包括修改时间)
shutil.copy2('src.txt', 'dir/backup.txt')

高级复制控制

# 自定义复制函数
def _copy_with_progress(src, dst, *, follow_symlinks=True):
    print(f"Copying {src} => {dst}")
    return shutil.copy2(src, dst, follow_symlinks=follow_symlinks)

shutil.copyfileobj(open('a.txt', 'r'), open('b.txt', 'w'), 
                  length=16*1024,  # 缓冲区大小
                  callback=lambda pos, total: print(f"{pos/total:.1%}"))

移动与删除

# 安全移动文件(跨设备自动复制+删除)
shutil.move('src.txt', '/mnt/backup/')

# 递归删除目录(危险操作!)
shutil.rmtree('temp_dir', 
             ignore_errors=False,  # 是否忽略错误
             onerror=lambda func, path, exc_info: print(f"Error in {func}({path})"))

4. 目录操作大全

目录复制

# 基本目录复制
shutil.copytree('src_dir', 'dst_dir',
               symlinks=False,         # 是否复制符号链接
               ignore=shutil.ignore_patterns('*.tmp', '__pycache__'),
               copy_function=shutil.copy2,
               dirs_exist_ok=True)     # Python 3.8+ 允许目标存在

# 自定义过滤逻辑
def ignore_logs(path, names):
    return {'access.log', 'error.log'} if Path(path).name == 'logs' else set()

shutil.copytree('app', 'backup', ignore=ignore_logs)

磁盘管理

# 查询磁盘使用情况
usage = shutil.disk_usage('/')
print(f"Total: {usage.total / 1e9:.1f}GB, Used: {usage.used / 1e9:.1f}GB")

# 修改目录所有者(需要root权限)
shutil.chown('data/', user='www-data', group='www-data')

5. 归档压缩处理

创建归档包

# 创建ZIP压缩包
shutil.make_archive('backup_2023', 'zip', 'src_dir')

# 带自定义根目录的tar.gz
shutil.make_archive('package', 'gztar', 
                   root_dir='dist', 
                   base_dir='lib',  # 只打包dist/lib目录
                   verbose=True)

解压操作

# 自动识别格式解压
shutil.unpack_archive('package.tar.gz', extract_dir='dist')

# 处理特殊格式
shutil.register_archive_format('myformat', 
                              lambda name, base_dir, **kw: custom_pack(),
                              description='My custom format')

6. 高级操作技巧

元数据管理

# 仅复制权限模式
shutil.copymode('source.txt', 'dest.txt')

# 复制所有stat信息
shutil.copystat('source_dir', 'dest_dir')

# 保留原始文件时间戳
def copy_preserve_all(src, dst):
    shutil.copy2(src, dst)
    st = os.stat(src)
    os.chown(dst, st.st_uid, st.st_gid)  # 需要权限

进度监控

class ProgressTracker:
    def __init__(self, total):
        self.total = total
        self.processed = 0
        
    def __call__(self, path, names):
        self.processed += len(names)
        print(f"{self.processed/self.total:.1%} completed")
        return set()

# 在copytree中使用
shutil.copytree('big_dir', 'backup', 
               ignore=ProgressTracker(len(list(Path('big_dir').rglob('*')))))

7. 异常处理机制

错误处理模式

try:
    shutil.rmtree('important_dir')
except FileNotFoundError:
    print("Directory already gone")
except PermissionError as e:
    print(f"Permission denied: {e.filename}")

自定义错误回调

def handle_rmtree_error(func, path, exc_info):
    import stat
    os.chmod(path, stat.S_IWRITE)
    func(path)

shutil.rmtree('locked_dir', onerror=handle_rmtree_error)

8. 性能优化策略

  1. 大文件复制

    # 使用更大的缓冲区
    with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
        shutil.copyfileobj(fsrc, fdst, length=1024*1024)  # 1MB buffer
    
  2. 并行处理

    from concurrent.futures import ThreadPoolExecutor
    
    def copy_item(src_path, dst_path):
        if src_path.is_dir():
            shutil.copytree(src_path, dst_path)
        else:
            shutil.copy2(src_path, dst_path)
    
    with ThreadPoolExecutor() as executor:
        futures = []
        for item in Path('src_dir').iterdir():
            futures.append(executor.submit(
                copy_item, 
                item, 
                Path('dst_dir')/item.name
            ))
        for future in futures:
            future.result()
    

9. 注意事项

  1. 路径处理规范

    # 使用Path对象作为参数(Python 3.6+)
    shutil.copy(Path('src.txt'), Path('dest.txt'))
    
  2. 安全删除策略

    def safe_remove(path: Path):
        if path.is_dir():
            shutil.rmtree(path, onerror=handle_errors)
        else:
            path.unlink(missing_ok=True)
    
  3. 跨平台注意事项

    # Windows长路径处理
    if sys.platform == 'win32':
        path = '\\\\?\\' + str(Path(long_path).resolve())
    

10. 危险操作警示

  1. 不可逆删除

    # 永远不要直接执行这种代码!
    shutil.rmtree('/', ignore_errors=True)  # 毁灭性操作!
    
  2. 符号链接陷阱

    # 默认会跟随符号链接
    shutil.copytree('src', 'dst', symlinks=False)  # 复制链接文件本身
    
  3. 权限覆盖风险

    # 可能降低文件安全性
    shutil.chown('config.ini', user='nobody')  # 需谨慎操作
    
  4. 静默覆盖问题

    # move操作可能覆盖现有文件
    if dst_path.exists():
        raise RuntimeError("Target already exists")
    shutil.move(src, dst)
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值