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 相关文章推荐
socket + select 完成伪并发操作的实例
Aug 15 Python
利用python爬取斗鱼app中照片方法实例
Dec 03 Python
Python之pandas读写文件乱码的解决方法
Apr 20 Python
django加载本地html的方法
May 27 Python
python+PyQT实现系统桌面时钟
Jun 16 Python
python 文本单词提取和词频统计的实例
Dec 22 Python
PySide和PyQt加载ui文件的两种方法
Feb 27 Python
详解Python 爬取13个旅游城市,告诉你五一大家最爱去哪玩?
May 07 Python
Python Django实现layui风格+django分页功能的例子
Aug 29 Python
python 利用pyttsx3文字转语音过程详解
Sep 25 Python
Django模型中字段属性choice使用说明
Mar 30 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
Nov 27 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
基于PHP+Ajax实现表单验证的详解
2013/06/25 PHP
PHP正则验证Email的方法
2015/06/15 PHP
PHP实现文件上传操作和封装
2020/03/04 PHP
一个选择最快的服务器转向代码
2009/04/27 Javascript
Jquery中增加参数与Json转换代码
2009/11/20 Javascript
在JQuery dialog里的服务器控件 事件失效问题
2010/12/08 Javascript
jQuery Ajax方法调用 Asp.Net WebService 的详细实例代码
2011/04/27 Javascript
使用javascript获取flash加载的百分比的实现代码
2011/05/25 Javascript
中文输入法不触发onkeyup事件的解决办法
2014/07/09 Javascript
JavaScript中判断整数的多种方法总结
2014/11/08 Javascript
javascript中关于&& 和 || 表达式的小技巧分享
2015/04/10 Javascript
JS实现的系统调色板完整实例
2016/12/21 Javascript
Bootstrap源码解读下拉菜单(4)
2016/12/23 Javascript
JS实现批量上传文件并显示进度功能
2017/06/27 Javascript
使用 Angular RouteReuseStrategy 缓存(路由)组件的实例代码
2019/11/01 Javascript
解决Layui数据表格显示无数据提示的问题
2019/11/14 Javascript
js实现div色块碰撞
2020/01/16 Javascript
React倒计时功能实现代码——解耦通用
2020/09/18 Javascript
详解React路由传参方法汇总记录
2020/11/29 Javascript
[09:40]DAC2018 4.5 SOLO赛 MidOne vs Miracle
2018/04/06 DOTA
Python中zip()函数用法实例教程
2014/07/31 Python
Python实现全排列的打印
2018/08/18 Python
python中dict字典的查询键值对 遍历 排序 创建 访问 更新 删除基础操作方法
2018/09/13 Python
Python实现的栈、队列、文件目录遍历操作示例
2019/05/06 Python
Pycharm 2020年最新激活码(亲测有效)
2020/09/18 Python
python pymysql库的常用操作
2020/10/16 Python
全面解析CSS Media媒体查询使用操作(推荐)
2017/08/15 HTML / CSS
美国家具网站:Cymax
2016/09/17 全球购物
北京泡泡网网络有限公司.net面试题
2012/07/17 面试题
如何写你的创业计划书
2014/01/07 职场文书
社区国庆节活动方案
2014/02/05 职场文书
三八节标语
2014/06/27 职场文书
2014年法务工作总结
2014/12/11 职场文书
python使用glob检索文件的操作
2021/05/20 Python
Nginx流量拷贝ngx_http_mirror_module模块使用方法详解
2022/04/07 Servers