Python实现SVN的目录周期性备份实例


Posted in Python onJuly 17, 2015

本文实例讲述了Python实现SVN的目录周期性备份方法。分享给大家供大家参考。具体如下:

起因:今天用SVN时,不小心把远程SVN服务器上的目录删掉了,然后在本地又手贱地还原了一下项目(eclipse中右键项目team => 还原),导致写了大半天的代码全部丢失,用多款数据恢复软件恢复也无果。一怒之下写了这个目录周期性备份小工具,每隔5秒备份源目录中的所有文件到目标目录(保留结构),保证目标目录中的文件只增不减。且每次只拷贝发生变化的文件(比较两个文件的MD5值)。

思考:虽然SVN也是一个版本管理软件,但在使用过程总觉得它的诸多操作挺别扭,相比而言Git更强大灵活。我自己理想中的版本控制软件至少应该考虑到一些让用户产生较强挫败的使用场景(也许大部分情况是因为用户误用,但如果误用情况也能考虑到,才能更体现软件的终极人文关怀嘛),比如删除远程服务器上的文件,我觉得应该设计成这样:即使用户删除了文件,文件还应该在一个缓冲区中呆1天(或几个小时,可以配置),然后由一个定时任务定时删除缓冲区中停留时间超过1天的文件。而不是立即物理删除。

TODO:
增加配置文件,做成命令行程序

md5_caculate.py:

# -*- coding: utf-8 -*-
#!/usr/bin/python
from hashlib import md5
import os 
def calMD5(str):
  m = md5()
  m.update(str)
  return m.hexdigest()
def calMD5ForFile(file):
  statinfo = os.stat(file)
  if int(statinfo.st_size) / (1024*1024) >= 1000:
#     print("File size > 1000, move to big file...")
    return calMD5ForBigFile(file)
  m = md5()
  f = open(file, 'rb')
  m.update(f.read())
  f.close()
  return m.hexdigest()
def calMD5ForFolder(dir, MD5File):
  outfile = open(MD5File,'w')
  for root, subdirs, files in os.walk(dir):
    for file in files:
      filefullpath = os.path.join(root, file)
      """print filefullpath"""
      filerelpath = os.path.relpath(filefullpath, dir)
      md5 = calMD5ForFile(filefullpath)
      outfile.write(filerelpath+' '+md5+"\n")
  outfile.close()
def calMD5ForBigFile(file):
  m = md5()
  f = open(file, 'rb')
  buffer = 8192  # why is 8192 | 8192 is fast than 2048
  while 1:
    chunk = f.read(buffer)
    if not chunk : break
    m.update(chunk)
  f.close()
  return m.hexdigest()
if __name__=="__main__":
  print(calMD5ForFile("e:/test/target/a/b/rabbit.txt"))

file_util.py:

# -*- coding: utf-8 -*-
#!/usr/bin/python
import os,shutil
from md5_caculate import calMD5ForFile
# 拷贝源目录到目标目录
def copyDir(srcDir, dstDir):
  if srcDir in dstDir: # 源目录包含在目标目录,则直接返回
    return
  if not os.path.isdir(srcDir):
    print(srcDir, "路径指定的源目录不存在!")
    return;
  if not os.path.exists(dstDir): # 目标目录不存在时则创建
    os.makedirs(dstDir)
  for fileOrDirName in os.listdir(srcDir): # 源目录下的所有文件(包括文件和目录) TODO BUG:如果srcDir为一个空目录?
#     fileOrDirPath = srcDir + "/" + fileOrDirName
    fileOrDirPath = os.path.join(srcDir, fileOrDirName)
    if os.path.isfile(fileOrDirPath): # 如果当前是一个子文件,则直接复制文件
      copyFile(fileOrDirPath, dstDir)
    if os.path.isdir(fileOrDirPath): # 如果当前是一个子目录,则递归复制目录
      copyDir(fileOrDirPath, os.path.join(dstDir, fileOrDirName))
# 拷贝源文件到目标目录
def copyFile(srcFile, dstDir):
  if not os.path.isfile(srcFile):
    print(srcFile, "路径指定的源文件不存在!")
    return
  fileName = os.path.basename(srcFile)
  dstFile = os.path.join(dstDir, fileName)
  if os.path.isfile(dstFile): # 有同名的目标文件,则检查MD5值是否相同,如果不同才Copy
    if calMD5ForFile(srcFile) != calMD5ForFile(dstFile):
      try:
        shutil.copy(srcFile, dstDir)
      except PermissionError:
        print("PermissionError occurs: ", srcFile)
  else:
    shutil.copy(srcFile, dstDir)
if __name__=="__main__":
  copyDir("e:/test/src", "e:/test/target")

backuper.py:

# -*- coding: utf-8 -*-
#!/usr/bin/python
import os, time
from file_util import copyDir
# -------------------------------------------------------------
# 定时备份源目录到目标目录
# version = 1.0
# author = Will
# -------------------------------------------------------------
# 定时备份源目录到目标目录,sleepIntervalSeconds为备份时间间隔秒数
def backupDir(srcDir, dstDir, sleepIntervalSeconds):
  if not os.path.isdir(srcDir):
    print("请指定要备份源目录并确保目录存在!")
    return;
  while True:
    print("备份:", srcDir, ",到:", dstDir)
    copyDir(srcDir, dstDir)
    print("开始休眠", sleepIntervalSeconds, "秒...")
    time.sleep(sleepIntervalSeconds)
if __name__=="__main__":
  backupDir("d:/Documents/workspace/workspace/griddle", "e:/backup/griddle", 20)

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
Python异常学习笔记
Feb 03 Python
python获取指定网页上所有超链接的方法
Apr 04 Python
深入学习Python中的上下文管理器与else块
Aug 27 Python
python 自定义异常和异常捕捉的方法
Oct 18 Python
python实现简单五子棋游戏
Jun 18 Python
基于spring boot 日志(logback)报错的解决方式
Feb 20 Python
Pytorch中的自动求梯度机制和Variable类实例
Feb 29 Python
Python中remove漏删和索引越界问题的解决
Mar 18 Python
python读取配置文件方式(ini、yaml、xml)
Apr 09 Python
完美解决pycharm 不显示代码提示问题
Jun 02 Python
python 装饰器重要在哪
Feb 14 Python
用 Python 定义 Schema 并生成 Parquet 文件详情
Sep 25 Python
Python的Django框架中设置日期和字段可选的方法
Jul 17 #Python
Python的Django框架下管理站点的基本方法
Jul 17 #Python
Django中更新多个对象数据与删除对象的方法
Jul 17 #Python
Django框架中数据的连锁查询和限制返回数据的方法
Jul 17 #Python
Django中对数据查询结果进行排序的方法
Jul 17 #Python
在Python的Django框架中获取单个对象数据的简单方法
Jul 17 #Python
Python的Django框架中的数据过滤功能
Jul 17 #Python
You might like
Discuz 6.0+ 批量注册用户名
2009/09/13 PHP
PHP 全角转半角实现代码
2010/05/16 PHP
file_get_contents("php://input", "r")实例介绍
2013/07/01 PHP
php sybase_fetch_array使用方法
2014/04/15 PHP
PHPStorm+XDebug进行调试图文教程
2016/06/13 PHP
js 点击按钮弹出另一页,选择值后,返回到当前页
2010/05/26 Javascript
jquery 使用点滴函数代码
2011/05/20 Javascript
Javascript图像处理思路及实现代码
2012/12/25 Javascript
js实现的切换面板实例代码
2013/06/17 Javascript
javascript获取浏览器类型和版本的方法(js获取浏览器版本)
2014/03/13 Javascript
Js实现手机发送验证码时按钮延迟操作
2014/06/20 Javascript
JavaScript中对象介绍
2014/12/31 Javascript
jQuery制作可自定义大小的拼图游戏
2015/03/30 Javascript
jQuery移动web开发中的页面初始化与加载事件
2015/12/03 Javascript
jqueryMobile使用示例分享
2016/01/12 Javascript
Nodejs如何复制文件
2016/03/09 NodeJs
JavaScript注册时密码强度校验代码
2017/06/30 Javascript
JS Object.preventExtensions(),Object.seal()与Object.freeze()用法实例分析
2018/08/25 Javascript
解决vue-cli项目打包出现空白页和路径错误的问题
2018/09/04 Javascript
详解Vue前端生产环境发布配置实战篇
2019/05/07 Javascript
angular8和ngrx8结合使用的步骤介绍
2019/12/01 Javascript
跟老齐学Python之正规地说一句话
2014/09/28 Python
Python的Django框架中的数据过滤功能
2015/07/17 Python
Python实现屏幕截图的代码及函数详解
2016/10/01 Python
python实现闹钟定时播放音乐功能
2018/01/25 Python
python实现汽车管理系统
2018/11/30 Python
python多线程并发及测试框架案例
2019/10/15 Python
opencv 图像轮廓的实现示例
2020/07/08 Python
python3处理word文档实例分析
2020/12/01 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
优秀学生事迹材料
2014/02/08 职场文书
2014年教师德育工作总结
2014/11/10 职场文书
自我推荐信怎么写
2015/03/24 职场文书
Mysql - 常用函数 每天积极向上
2021/04/05 MySQL
Python打包exe时各种异常处理方案总结
2021/05/18 Python
MySQL优化之慢日志查询
2022/06/10 MySQL