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判断变量是否已经定义的方法
Aug 18 Python
基于Python实现的百度贴吧网络爬虫实例
Apr 17 Python
python中尾递归用法实例详解
Apr 28 Python
python黑魔法之参数传递
Feb 12 Python
Python实现统计代码行的方法分析
Jul 12 Python
PyChar学习教程之自定义文件与代码模板详解
Jul 17 Python
Python实现读取及写入csv文件的方法示例
Jan 12 Python
解决Pycharm后台indexing导致不能run的问题
Jun 27 Python
简单了解python filter、map、reduce的区别
Jan 14 Python
python自动下载图片的方法示例
Mar 25 Python
Tensorflow使用Anaconda、pycharm安装记录
Jul 29 Python
解决Python中的modf()函数取小数部分不准确问题
May 28 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
第六节--访问属性和方法
2006/11/16 PHP
JQuery 获取和设置Select选项的代码
2010/02/07 Javascript
IE之动态添加DOM节点触发window.resize事件
2010/07/27 Javascript
关于Javascript模块化和命名空间管理的问题说明
2010/12/06 Javascript
了解一点js的Eval函数
2012/07/26 Javascript
jQuery(js)获取文字宽度(显示长度)示例代码
2013/12/31 Javascript
简单选项卡 js和jquery制作方法分享
2014/02/26 Javascript
js 模式窗口(模式对话框和非模式对话框)的使用介绍
2014/07/17 Javascript
jquery实现鼠标滑过显示提示框的方法
2015/02/05 Javascript
JavaScript获得表单target属性的方法
2015/04/02 Javascript
jqTransform美化表单
2015/10/10 Javascript
前端微信支付js代码
2016/07/25 Javascript
jQuery复合事件用法示例
2017/06/10 jQuery
详解vue-admin和后端(flask)分离结合的例子
2018/02/12 Javascript
总结js函数相关知识点
2018/02/27 Javascript
vue-cli3使用 DllPlugin 实现预编译提升构建速度
2019/04/24 Javascript
Vue.extend 编程式插入组件的实现
2019/11/18 Javascript
原生js实现轮播图特效
2020/05/04 Javascript
谈谈JavaScript中的函数
2020/09/08 Javascript
[55:44]完美世界DOTA2联赛决赛 FTD vs Phoenix 第二场 11.08
2020/11/11 DOTA
python创建线程示例
2014/05/06 Python
Python中文编码那些事
2014/06/25 Python
python中使用xlrd读excel使用xlwt写excel的实例代码
2018/01/31 Python
对python判断ip是否可达的实例详解
2019/01/31 Python
python3实现小球转动抽奖小游戏
2020/04/15 Python
Django发送邮件功能实例详解
2019/09/02 Python
Python协程 yield与协程greenlet简单用法示例
2019/11/22 Python
Python continue语句实例用法
2020/02/06 Python
将 Ubuntu 16 和 18 上的 python 升级到最新 python3.8 的方法教程
2020/03/11 Python
小学优秀辅导员事迹材料
2014/05/11 职场文书
2015年小学数学教师个人工作总结
2015/05/25 职场文书
单身证明范本
2015/06/15 职场文书
2015最新婚礼司仪主持词
2015/06/30 职场文书
初中地理教学反思
2016/02/19 职场文书
ElementUI实现el-form表单重置功能按钮
2021/07/21 Javascript
2021年国产动漫公司排行前十名,玄机科技上榜,第二推出过铠甲勇士
2022/03/18 杂记