将GAE站点的代码打包成zip包并下载,这就可以定期保存站点代码。因为GAE不提空版本控制,每次更新只保存最新代码。
来自:http://xuming.net/2008/06/gae-zipme.html 源码下载 不过这个链接我上不去。所以直接用一下代码:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
##########################################################################
ZipMe : GAE Content Downloader # manatlan
##########################################################################
Just add this lines in your app.yaml :
- url: /zipme
script: zipme.py
##########################################################################
"""
from google.appengine.ext import webapp
from google.appengine.api import users
import wsgiref.handlers
import zipfile
import os,re,sys,stat
from cStringIO import StringIO
def createZip(path):
def walktree (top = ".", depthfirst = True):
names = os.listdir(top)
if not depthfirst:
yield top, names
for name in names:
try:
st = os.lstat(os.path.join(top, name))
except os.error:
continue
if stat.S_ISDIR(st.st_mode):
for (newtop, children) in walktree (os.path.join(top, name),
depthfirst):
yield newtop, children
if depthfirst:
yield top, names
list=[]
for (basepath, children) in walktree(path,False):
for child in children:
f=os.path.join(basepath,child)
if os.path.isfile(f):
f = f.encode(sys.getfilesystemencoding())
list.append( f )
f=StringIO()
file = zipfile.ZipFile(f, "w")
for fname in list:
nfname=os.path.join(os.path.basename(path),fname[len(path)+1:])
file.write(fname, nfname , zipfile.ZIP_DEFLATED)
file.close()
f.seek(0)
return f
class ZipMaker(webapp.RequestHandler):
def get(self):
if users.is_current_user_admin():
folder = os.path.dirname(__file__)
self.response.headers['Content-Type'] = 'application/zip'
self.response.headers['Content-Disposition'] = 'attachment; filename="%s.zip"' % os.path.basename(folder)
fid=createZip(folder)
while True:
buf=fid.read(2048)
if buf=="": break
self.response.out.write(buf)
fid.close()
else:
self.response.headers['Content-Type'] = 'text/html'
self.response.out.write("<a href=\"%s\">You must be admin</a>." %
users.create_login_url("/zipme"))
def main():
application = webapp.WSGIApplication(
[('/zipme', ZipMaker)],
debug=False)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == "__main__":
main()
根据这段代码,新进一个py脚本,放上代码,并修改app.yaml如代码首部。就OK了。
另外,看了下代码,有些可以改进的地方,比如说遍历站点文件夹的方式,明明可以用walk的。不过,一个很巧妙的地方是,因为GAE不支持写文件,那么file = zipfile.ZipFile(f, "w")这个是用"w"方式的,这个f不是物理文件,而是用了StringIO,所以就可以实现了。
StringIO(...) StringIO([s]) -- Return a StringIO-like stream for reading or writing
再另外,下载下来的zip文件夹对比本地的工程文件夹,还是有区别的。
首先,zip文件夹下文件都变成只读文件。这估计是GAE上是只读的。
其次,.pyc都不会上传。
最后,media文件夹没有打包,是因为GAE上真正没有放在工程目录下而是放在别的地方,还是因为上述代码中的walktree没有生成?越看walktree越别扭。——测试 http://lizziesky.appspot.com/test/ 得到目录结构就是不包含media文件夹的,估计是放在别的地方了。