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进阶篇之字典操作总结
Nov 16 Python
Python深入06——python的内存管理详解
Dec 07 Python
PyTorch的深度学习入门之PyTorch安装和配置
Jun 27 Python
python 修改本地网络配置的方法
Aug 14 Python
python语言线程标准库threading.local解读总结
Nov 10 Python
TensorFlow2.0矩阵与向量的加减乘实例
Feb 07 Python
在python3中使用shuffle函数要注意的地方
Feb 28 Python
Python如何优雅删除字符列表空字符及None元素
Jun 25 Python
Python的控制结构之For、While、If循环问题
Jun 30 Python
scrapy redis配置文件setting参数详解
Nov 18 Python
Python虚拟环境virtualenv是如何使用的
Jun 20 Python
Python实现Excel文件的合并(以新冠疫情数据为例)
Mar 20 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
php中使用preg_match_all匹配文章中的图片
2013/02/06 PHP
PHP中使用cURL实现Get和Post请求的方法
2013/03/13 PHP
一个经典实用的PHP图像处理类分享
2014/11/18 PHP
php实现插入数组但不影响原有顺序的方法
2015/03/27 PHP
为你总结一些php系统类函数
2015/10/21 PHP
PHP获取当前日期及本周一是几月几号的方法
2017/03/28 PHP
TP5多入口设置实例讲解
2020/12/15 PHP
JS焦点图切换,上下翻转
2011/05/12 Javascript
JQUERY对单选框(radio)操作的小例子
2013/04/25 Javascript
JS 删除字符串最后一个字符的实现代码
2014/02/20 Javascript
JavaScript实现Java中StringBuffer的方法
2015/02/09 Javascript
nodejs实现HTTPS发起POST请求
2015/04/23 NodeJs
Avalon中文长字符截取、关键字符隐藏、自定义过滤器
2016/05/18 Javascript
JavaScript事件学习小结(一)事件流
2016/06/09 Javascript
基于Bootstrap的UI扩展 StyleBootstrap
2016/06/17 Javascript
jQuery实现文字超过1行、2行或规定的行数时自动加省略号的方法
2018/03/28 jQuery
关于HTML5的data-*自定义属性的总结
2018/05/05 Javascript
vue+iview分页组件的封装
2020/11/17 Vue.js
详解ES6 中的Object.assign()的用法实例代码
2021/01/11 Javascript
Python的Django框架中的表单处理示例
2015/07/17 Python
使用Python的urllib2模块处理url和图片的技巧两则
2016/02/18 Python
Python实现的归并排序算法示例
2017/11/21 Python
Python实现屏幕截图的两种方式
2018/02/05 Python
基于python log取对数详解
2018/06/08 Python
Django后端接收嵌套Json数据及解析详解
2019/07/17 Python
Python基于内置库pytesseract实现图片验证码识别功能
2020/02/24 Python
解决Keyerror ''acc'' KeyError: ''val_acc''问题
2020/06/18 Python
Python爬虫爬取新闻资讯案例详解
2020/07/14 Python
html5基础教程常用技巧整理
2013/08/20 HTML / CSS
荷兰鞋类购物网站:Donelli
2019/05/24 全球购物
C语言笔试集
2012/07/24 面试题
环境工程求职简历的自我评价范文
2013/10/24 职场文书
电脑教师的教学自我评价
2013/11/26 职场文书
演讲稿怎么写
2014/01/07 职场文书
我的中国梦演讲稿800字
2014/08/19 职场文书
个人收入证明范本
2015/06/12 职场文书