俺最新.emcas配置地址是:http://github.com/smallfish/editor/blob/master/emacs/.emacs
最近手痒,看到不少牛x人物都是用emacs,遂在windows下装一个玩玩。
下载地址:http://ftp.gnu.org/pub/gnu/emacs/windows/emacs-23.1-bin-i386.zip
解压到:D:\emacs-23.1
可以看到bin、etc、lisp等目录。主要运行都在bin目录。
runemacs.exe 这个就是运行文件拉,可以发送到桌面快捷方式。
可以运行一下addpm.exe这个,其作用就是把emacs加入到开始程序菜单里。
试着运行一下runemacs.exe,可以发现默认光标的位置,那是一个入门教程喔,还是中文的耶~
建议都看下这个入门的教程,常用的快捷键都有说明。
接下来加点常用的功能把,比如显示行号,goto line的功能。(俺也只配置了这个两项)
配置文件主要是_emacs或者.emacs,win下建议_emacs,点号开头的文件需要到cmd下才行。
_emacs文件放到哪儿呢?俺是直接修改了win注册表选项。
选项是:HKEY_CURRENT_USER\Software\GNU\Emacs,注意GNU\Emacs是需要新建的。接下来在Emacs里新建一个HOME项,值是你的emacs路径,比如我的:D:\emacs-23.1\bin。
然后需要做的就是把_emacs文件在这个bin目录下。
经过几经周折,显示行号和goto功能的配置如下:
(global-linum-mode 1) (global-set-key [(meta g)] 'goto-line)
第一行是显示行号
第二行是设置meta+g转到goto功能,meta在windows下可以用alt来操作。
其他功能以后在后续补上,快捷键挺多,用了一会手指发酸。C-x 数字(1 2 3)挺好,可以开多窗口浏览了。
简介
git是由Linus Torvalds编写的一个开放源码的版本控制系统. 它的主要目标是高度分散, 效率超过其他竞争对手.
我就是使用git维护本网站. 我知道git不应该这样的粗重任务的使用, 即每一个开发者维护一份代码拷贝, 但是它工作的很好, 所有我使用它.
本文的目的就是说明如何在家里或者笔记本里维护一个本地拷贝, 然后让这些修改提交到互联网主机上. 下面就是介绍如何设置.
安装
# Gentoo emerge git
# Debian/Ubuntu apt-get install git-core
# RedHat/Fedora yum install git
初始化
你会进入你的服务器的目录和初始化git仓库.
# 进入你的web目录 cd /$wherever/html/
# 初始化仓库 git init
# 添加所有内容 git add .
# 提交 -m备注 git commit -a -m "The Initial Import."
然后返回你的html父目录, 克隆新的git-ized web目录.
# 返回你的html目录 cd ..
# 克隆你的web目录到 html.git git clone --bare html html.git
现在你已经初始化好了仓库, 并将整个目录(递归)到该库中, 并进行了初次提交, 为web目录建立了一个git克隆. 这个git目录(html.git)是整个过程的关键.
获取一份开发环境的拷贝
1. 转到你的开发系统
2. 安装git
3. 从你的开发目录运行下面命令
git clone ssh://yoursite.com/path/to/html.git
现在已经获得一个完整的网站服务器版本的本地拷贝.
使你的web目录克隆Git目录
记住, 你的html.git是这里的关键, 而不是现有的html目录, 所以你要切换出来, 备份目录, 然后:
# 备份html目录, 然后克隆html.git mv html html.backup; git clone html.git
这在当前目录获取一份html.git的拷贝, 当然名字还是html. 这就是为什么备份旧的html目录.
自动推送修改
把你的html.git目录添加到post-update钩子中
cd ../htdocs env -i git pull
修改钩子程序为可执行
chmod +x post-update
在你的开发环境的变动
现在编辑的网站, 打开一个新的TextMate项目(你使用TextMate对吗?), 并拖动到html克隆目录. 整个结构都准备好了.
1. 通常的变动
2. 保存更改
3. 运行下面的程序, 例如(QuickSearchBox, TextMate等)
# This is for an OS X box cd /Users/daniel/Development/html/ git commit -a -m "Another update." git push
这基本上是更新到git仓库最重要的两个命令: commit(注意:你的标记(如果想回滚的话))和push(推送到服务器).
[根据你的操作系统和git安装, 你可能需要chmod +x 钩子程序, 然后再继续]
现在你只需要激活post-update 钩子程序, 将会自动的获取web目录.
如果你在服务器端的操作基本也是相同的git commit和git push, 然后你的开发环境下git pull同步备份就可以了. 当然你还可以使用脚本, 如果你需要的话.
原文参见: http://danielmiessler.com/blog/using-git-to-maintain-your-website
tornado.database模块简单包装了下对MySQL的操作,短小精悍。
无奈源码中无连接池功能,遂加上了一段DBUtils模块功能。
主要修改了reconnect()方法,大致在database.py第86行左右。(tornado 0.2 win版)
原代码如下:
def reconnect(self): """Closes the existing database connection and re-opens it.""" self.close() self._db = MySQLdb.connect(**self._db_args) self._db.autocommit(True)
修改后:
def reconnect(self): """Closes the existing database connection and re-opens it.""" self.close() try: from DBUtils import PooledDB pool_con = PooledDB.PooledDB(creator=MySQLdb, **self._db_args) self._db = pool_con.connection() except: self._db = MySQLdb.connect(**self._db_args) self._db.autocommit(True)
至于安装DBUtils模块可以去http://pypi.python.org/pypi/DBUtils/下载,也可以简单的用easy_install:
easy_install -U DBUtils
PooledDB有这么几个参数:
* creator 可以生成 DB-API 2 连接的任何函数或 DB-API 2 兼容的数据库连接模块。 * mincached 启动时开启的空连接数量(缺省值 0 意味着开始时不创建连接) * maxcached 连接池使用的最多连接数量(缺省值 0 代表不限制连接池大小) * maxshared 最大允许的共享连接数量(缺省值 0 代表所有连接都是专用的) * maxconnections 最大允许连接数量(缺省值 0 代表不限制) * blocking 设置在达到最大数量时的行为(缺省值 0 或 False) * maxusage 单个连接的最大允许复用次数(缺省值 0 或 False 代表不限制的复用) * setsession: 一个可选的SQL命令列表用于准备每个会话,如 ["set datestyle to german", ...]
creator 函数或可以生成连接的函数可以接受这里传入的其他参数,例如主机名、数据库、用户名、密码等。你还可以选择传入creator函数的其他参数,允许失败重连和负载均衡。
具体可以参照下:http://www.webwareforpython.org/DBUtils/Docs/UsersGuide.zh.html
这是一篇关于pysvn模块的指南.
完整和详细的API请参考 pysvn Programmer’s Reference.
pysvn是操作Subversion版本控制的Python接口模块. 这个API接口可以管理一个工作副本, 查询档案库, 和同步两个.
该API不能创建新的仓库; 只能作用在现有仓库上. 如果你需要创建一个仓库, 请使用Subversion的svnadmin命令.
使用这个API, 你可以check out一份工作拷贝, 添加, 编辑, 和删除工作文件, 和check in, 比较, 或者放弃更改. 仓库属性, 如关键字扩展, 行字符结束, 或者忽略的列表也可以检查和控制.
Subversion 模型
Subversion是一个更新-编辑-提交的模型. 首先在本地建立一个工作副本. 在工作副本上进行修改, 最后提交到中央仓库 (可以是本地或者远程).
这个模型允许多人偶尔会同时修改同一个文件. 大多情况下. Subversion不会干预合并这些不同修改, 如果一个提交失败, 用户或者应用则要重新检查和修改然后再次提交.
常见任务
本节给出一些使用pysvn接口的常用例子. 业务可以会递归的处理目录. 添加参数recurse=False以防止这种行为; 例如, 你可以需要添加内容没有增加一个目录.
check out一份工作副本
import pysvn client = pysvn.Client() #check out the current version of the pysvn project client.checkout('http://localhost/example/trunk', './examples/pysvn') #check out revision 11 of the pysvn project client.checkout('http://localhost/example/trunk', './examples/pysvn-11', revision=pysvn.Revision(pysvn.opt_revision_kind.number, 11))
这是一个建立example测试项目的例子,目录是examples/pysvn. 这个项目是用在剩下的例子.
添加一个文件或者目录到仓库
import pysvn # write a file foo.txt f = file('./examples/pysvn/foo.txt', 'w') f.write('Sample versioned file via pithon\n') f.close() client = pysvn.Client() #schedule the addition; # the working copy will now track the file as a scheduled change client.add('./examples/pysvn/foo.txt') #committing the change actually adds the file to the repository client.checkin(['./examples/pysvn/foo.txt'], 'Adding a sample file')
这个例子是在工作副本中创建了’foo.txt’文件, 然后添加到仓库. 请注意Client.import_()命令会同时增加和提交. 大多数应用, 会在许多修改后再提交.
更新工作副本
import pysvn client = pysvn.Client() client.update('./examples/pysvn')
从仓库中更新其他用户修改并保存到本地副本. 大多数应用应该经常这样做以防止冲突.
提交更新到仓库
import pysvn # edit the file foo.txt f = open('./examples/pysvn/foo.txt', 'w') f.write('Sample versioned file via python\n') f.close() # checkin the change with a log message client = pysvn.Client() client.checkin(['./examples/pysvn'], 'Corrected spelling of python in foo.txt')
提交到Subversion是原子的. 要么所有修改都成功提交, 要么提交失败. 大部分应用会提交工作副本所有修改, 如本例所示, 或者通过个别文件或者目录, 但必须是同一单位.
放弃工作副本修改
import pysvn # edit the file foo.txt f = file('./examples/pysvn/foo.txt', 'w') f.write('This change will never be seen\n') f.close() #discard the edits client = pysvn.Client() client.revert('./examples/pysvn/foo.txt')
这丢弃在工作拷贝和恢复的文件或目录的任何未提交的未经编辑的状态变化.
正在计划增加或移除留无版本或恢复到工作拷贝.
重命名或者移动文件
import pysvn client = pysvn.Client() #rename the file client side client.move('./examples/pysvn/foo.txt', './examples/pysvn/foo2.txt') #checkin the change removes the file from the repository client.checkin(['./examples/pysvn/foo.txt', './examples/pysvn/foo2.txt'], 'Foo has become Foo2')
移动或重命名文件删除旧路径或名称的文件, 并增加了在新的位置, 同时保留以前的版本有关的信息.
在这个例子里, 我们通过文件名Client.checkin()传递父目录也将是有效的.
转移和合并可以在服务器端单步完成; 可以参见仓库任务的那节例子.
从仓库中删除文件或目录
import pysvn client = pysvn.Client() #schedule the removal; # the file will be removed from the working copy client.remove('./examples/pysvn/foo2.txt') #committing the change removes the file from the repository client.checkin(['./examples/pysvn/foo2.txt'], 'Removing sample file')
有些人把删除的文件, 或是用完全清除存储库目录. 该文件仍然存在于以前的版本, 可以通过检查或以其他方式进行审查以前修订的内容检索.
确定等待变动
import pysvn client = pysvn.Client() changes = client.status('./examples/pysvn') print 'files to be added:' print [f.path for f in changes if f.text_status == pysvn.wc_status_kind.added] print 'files to be removed:' print [f.path for f in changes if f.text_status == pysvn.wc_status_kind.deleted] print 'files that have changed:' print [f.path for f in changes if f.text_status == pysvn.wc_status_kind.modified] print 'files with merge conflicts:' print [f.path for f in changes if f.text_status == pysvn.wc_status_kind.conflicted] print 'unversioned files:' print [f.path for f in changes if f.text_status == pysvn.wc_status_kind.unversioned]
生成差异或补丁
import pysvn client = pysvn.Client() diff_text = client.diff('./tmp-file-prefix-', '.')
获取仓库URL
import pysvn client = pysvn.Client() entry = client.info('.') print 'Url:',entry.url
仓库任务
本节说明任务的例子, 操纵或检查仓库.虽然共同任务, 通过本地工作副本时间的变化, 这些任务直接影响到库
获取仓库目录的清单
import pysvn client = pysvn.Client() entry_list = client.ls('.')
从仓库获取文件内容
import pysvn client = pysvn.Client() file_content = client.cat('file.txt')
创建一个标记或分支
import pysvn client = pysvn.Client() log_message = "reason for change" def get_log_message(): return True, log_message client.callback_get_log_message = get_log_message client.copy('http://svnrepo.com/svn/trunk', 'http://svnrepo.com/svn/tag/%s' % tag_name )
从仓库中转移或者重命名
import pysvn client = pysvn.Client() client.move( 'file_old.txt', 'file_new.txt' )
锁定文件
import pysvn client = pysvn.Client() client.lock( 'file.txt', 'reason for locking' )
锁定文件并锁定其他用户或者工作副本
import pysvn client = pysvn.Client() client.lock( 'file.txt', 'reason for locking', force=True )
解锁
import pysvn client = pysvn.Client() client.unlock( 'file.txt' )
解锁文件并锁定其他用户或工作副本
import pysvn client = pysvn.Client() client.unlock( 'file.txt', force=True )
测试锁定文件
Method 1:
all_entries = self.client.info2( path, recurse=False ) for path, info in all_entries: if info['lock']: if info['lock']['token'] != '': print '%s is locked' % path print info['lock']['comment']
Method 2:
all_status = self.client.status( path, recurse=False, update=True ) for status in all_status: if status.entry is not None: if status.entry.lock_token is not None: print '%s is locked' % status.path
Cython代码跟Python不一样,必须要编译。
编译经过两个阶段:
* Cython编译.pyx文件为.c文件
* C编译器会把.c文件编译成.so文件(Windows上是.pyd)
以下会分节介绍几种方式来建立你的扩展模块。
注意: -a 选项,如果使用该选项将会为.c文件生成一份很漂亮的HTML文件,双击高亮的章节部分会展开代码,这对理解,优化和调试模块将会非常有帮助。
命令行
从命令行执行Cython编译器,输入选项和.pyx文件列表。
$ cython -a yourmod.pyx
会生成一个yourmod.c文件(指定-a选项会生成一个HTML文件)
编译.c文件取决于你的操作系统,请参考下如何在你的系统写Python扩展模块文档。
下面是一个Linux系统的例子:
$ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing \ -I/usr/include/python2.5 -o yourmod.so yourmod.c
gcc需要提供包含的文件和扩展库的链接。
在目录里会生成yourmod.so文件。
现在只需要导入你的yourmod模块就可以了。
Distutils
确保你的系统已经安装好Distutils。
下面假设需要编译的文件叫hello.pyx。
建立一个setup.py的脚本:
from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext ext_modules = [Extension("hello", ["hello.pyx"])] setup( name = ’Hello world app’, cmdclass = {’build_ext’: build_ext}, ext_modules = ext_modules )
在命令行执行:python setup.py build_ext –inplace
现在可以在shell或者脚本里正常导入使用了。
Pyximport
在纯Python代码里调用Cython代码:
>>> import pyximport; pyximport.install() >>> import helloworld Hello World
这仅仅是简单调用Cython,不需要C库也不需要构建脚本。
当然也可以实验性的在Python调用。允许在Python模块中运行Cython代码在任何一个.pyx和.py模块。这包
括标准库和包。如果Cython编译失败的话,pyximport会返回到加载失败的模块处。
.py安装是这样:
>>> pyximport.install(pyimport = True)
在偶的ubuntu里编写pyrex程序编译成so还是挺爽的,用 timeit.Timer 测试性能提升不少,今天在windows也尝试了一番。
需要的工具有:
- Pyrex http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
- Dev C++ http://www.bloodshed.net/devcpp.html
Pyrex 可以通过easy_install Pyrex来安装。
Dev C++ 安装完在系统环境变量Path里加上Dev C++安装目录/bin 目录。
测试扩展代码:
# file: foo.pyx """ simple pyrex module """ cdef class Foo: """ foo doc ... """ cdef char *name def __init__(self, name): self.name = name def __repr__(self): return "foo names: %s" % (self.name) # file: setup.py from distutils.core import setup from distutils.extension import Extension from Pyrex.Distutils import build_ext setup( name='foo', ext_modules=[Extension("foo", ["foo.pyx"])], cmdclass={'build_ext':build_ext} )
写好两个文件后,进入命令提示符:
C:\>python setup.py build_ext --inplace -c mingw32 running build_ext pyrexc foo.pyx --> foo.c building 'foo' extension creating build creating build\temp.win32-2.5 creating build\temp.win32-2.5\Release C:\Program Files\DEV-CPP\Bin\gcc.exe -mno-cygwin -mdll -O -Wall -ID:\Python25\include -ID:\Python25\PC -c foo.c -o build\temp.win32-2.5\Release\foo.o writing build\temp.win32-2.5\Release\foo.def C:\Program Files\DEV-CPP\Bin\dllwrap.exe -mno-cygwin -mdll -static --entry _DllMain@12 --output-lib build\temp.win32-2.5\Release\libfoo.a --def build\temp.win32-2.5\Release\foo.def -s build\temp.win32-2.5\Release\foo.o -LD:\Python25\libs -L D:\Python25\PCBuild -lpython25 -lmsvcr71 -o foo.pyd
编译完毕,可以看到当前目录下多了:build目录、foo.c、foo.pyd。foo.pyd 即是编译好的二进制扩展。
C:\>python ActivePython 2.5.0.0 (ActiveState Software Inc.) based on Python 2.5 (r25:51908, Mar 9 2007, 17:40:28) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import foo <module 'foo' from 'foo.pyd'> >>> foo.Foo("smallfish") foo names: smallfish
MySQL Query Profile MySQL 5.0.37 以上开始支持 MySQL Query Profiler, 可以查询到此 SQL 会执行多少时间, 并看出 CPU/Memory 使用量, 执行过程中 System lock, Table lock 花多少时间等等.
详细可以参见官方文档:Using the New MySQL Query Profiler
启动
mysql> set profiling=1; Query OK, 0 rows affected (0.00 sec)
测试查询
mysql> select count(*) from client where broker_id=2; +----------+ | count(*) | +----------+ | 200 | +----------+ 1 row in set (0.00 sec)
查看profiles
mysql> show profiles; +----------+------------+-----------------------------------------------+ | Query_ID | Duration | Query | +----------+------------+-----------------------------------------------+ | 0 | 0.00007300 | set profiling=1 | | 1 | 0.00044700 | select count(*) from client where broker_id=2 | +----------+------------+-----------------------------------------------+ 2 rows in set (0.00 sec)
查看单条profile
mysql> show profile for query 1; +--------------------+------------+ | Status | Duration | +--------------------+------------+ | (initialization) | 0.00006300 | | Opening tables | 0.00001400 | | System lock | 0.00000600 | | Table lock | 0.00001000 | | init | 0.00002200 | | optimizing | 0.00001100 | | statistics | 0.00009300 | | preparing | 0.00001700 | | executing | 0.00000700 | | Sending data | 0.00016800 | | end | 0.00000700 | | query end | 0.00000500 | | freeing items | 0.00001200 | | closing tables | 0.00000800 | | logging slow query | 0.00000400 | +--------------------+------------+ 15 rows in set (0.00 sec) mysql> alter table t engine=myisam; Query OK, 112050 rows affected (0.64 sec) Records: 112050 Duplicates: 0 Warnings: 0 mysql> show profiles; +----------+------------+-----------------------------------------------+ | Query_ID | Duration | Query | +----------+------------+-----------------------------------------------+ | 0 | 0.00007300 | set profiling=1 | | 1 | 0.00044700 | select count(*) from client where broker_id=2 | | 2 | 0.00003400 | set profiling=0 | | 3 | 0.00007400 | set profiling=1 | | 4 | 0.63789700 | alter table t engine=myisam | | 5 | 0.00004000 | set profiling=0 | +----------+------------+-----------------------------------------------+ 6 rows in set (0.00 sec) mysql> show profile for query 4; +----------------------+------------+ | Status | Duration | +----------------------+------------+ | (initialization) | 0.00002900 | | checking permissions | 0.00000800 | | init | 0.00004000 | | Opening table | 0.00009400 | | System lock | 0.00000500 | | Table lock | 0.00000700 | | setup | 0.00004200 | | creating table | 0.00195800 | | After create | 0.00010900 | | copy to tmp table | 0.52264500 | | rename result table | 0.11289400 | | end | 0.00004600 | | query end | 0.00000700 | | freeing items | 0.00001300 | +----------------------+------------+ 14 rows in set (0.00 sec)
查看cpu资源等信息
mysql> show profile cpu for query 4; +----------------------+------------+------------+------------+ | Status | Duration | CPU_user | CPU_system | +----------------------+------------+------------+------------+ | (initialization) | 0.00002900 | 0.00000000 | 0.00000000 | | checking permissions | 0.00000800 | 0.00000000 | 0.00000000 | | init | 0.00004000 | 0.00000000 | 0.00000000 | | Opening table | 0.00009400 | 0.00100000 | 0.00000000 | | System lock | 0.00000500 | 0.00000000 | 0.00000000 | | Table lock | 0.00000700 | 0.00000000 | 0.00000000 | | setup | 0.00004200 | 0.00000000 | 0.00000000 | | creating table | 0.00195800 | 0.00000000 | 0.00100000 | | After create | 0.00010900 | 0.00000000 | 0.00000000 | | copy to tmp table | 0.52264500 | 0.55591600 | 0.04199300 | | rename result table | 0.11289400 | 0.00199900 | 0.00000000 | | end | 0.00004600 | 0.00000000 | 0.00000000 | | query end | 0.00000700 | 0.00000000 | 0.00000000 | | freeing items | 0.00001300 | 0.00000000 | 0.00000000 | +----------------------+------------+------------+------------+ 14 rows in set (0.00 sec)
其他属性列表
* ALL – displays all information
* BLOCK IO – displays counts for block input and output operations
* CONTEXT SWITCHES – displays counts for voluntary and involuntary context switches
* IPC – displays counts for messages sent and received
* MEMORY – is not currently implemented
* PAGE FAULTS – displays counts for major and minor page faults
* SOURCE – displays the names of functions from the source code, together with the name and line number of the file in which the function occurs
* SWAPS – displays swap counts
设定profiling保存size
mysql> show variables where variable_name='profiling_history_size'; # 默认15条
关闭
mysql> set profiling=0;
其实MySQL-python安装很简直,以前一直也没在意,今天发觉换了1.2.3新版本,ms蹦出很多问题来了。
做个记录,防止以后有问题无处可查。
一般步骤是:
1. 安装easy_install
shell > wget http://peak.telecommunity.com/dist/ez_setup.py shell > python ez_setup.py
会自动根据本机的py版本选择对应的egg,安装完可以看到有/usr/bin/easy_install程序了
2. 安装MySQL-python
shell > easy_install MySQL-python
到这里安装算是完成了,不过接下来测试就郁闷了。
在import MySQLdb出现了两个错误:
a). ImportError: libmysqlclient_r.so.15: cannot open shared object file: No such file or directory
这个错误一般解决比较简单,把路径加入到LD_LIBRARY_PATH即可,不过偶的现象比较强,因为没装MySQL,哈哈
b). ImportError: /lib/tls/libc.so.6: version `GLIBC_2.4' not found
解决这个错误的办法是不用easy_install了,直接下载MySQL-python-1.2.2.tar.gz包,然后就是三步走:
shell > tar zxvf MySQL-python-1.2.2.tar.gz shell > cd MySQL-python-1.2.2 shell > python setup.py install
看到有人在坛子里询问在GAE如何发布web.py有关问题,就尝试了一把。具体安装和使用过程如下,请对照自己本地路径相应修改:
1. 复制本地对应web.py目录到GAE对应应用目录
比如:D:\Python25\Lib\site-packages\web 到 e:\googleapp\pynotes
2. 写测试代码
app.yaml
application: pynotes version: 1 runtime: python api_version: 1 handlers: - url: /.* script: home.py
home.py
import web render = web.template.render('templates/') urls = ( '/', 'index' ) class index: def GET(self): web.header('Content-type', 'text/html') name = 'smallfish' return render.index(name) app = web.application(urls, globals()) main = app.cgirun() # 这行是发布到GAE的关键
templates/index.html
$def with (name) hello, $name. test by web.py
3. 发布到GAE,测试
e:\googleapp>appcfg.py update pynotes/
到这里,一个简单web.py应用就完成了,然后刷新。GAE显示500 Error!
看后台GAE Log显示错误信息:”No module named templates“,去web.py官方溜达了一圈,发现在其cookbook里有一篇文档《How to use templates on Google App Engine》,里面说的很明白啦。
因为web.py的模板在GAE上文件系统会有所限制,所有本地得compile一下,具体命令是:python web/template.py –compile templates 最后一个参数是本地对应模板目录templates,如果有多个模板目录则一次运行一次。运行完会在templates会生成一个__init__.py,里面内容有兴趣可以看看,很眼熟的哦。
4. 再次发布到GAE,可以看到OK拉!
Mako是什么?Moko是Python写的一个模板库,Python官网python.org用的就是它哦。其他废话也就不累赘了,直接来点代码,方便阅读与了解把。
(Mako官网地址:http://www.makotemplates.org/ ,可以下载安装包,推荐使用easy_install安装)
from mako.template import Template mytemplate = Template("hello world!") print mytemplate.render() mytemplate = Template("hello, ${name}!") print mytemplate.render(name="jack")
代码可以参考官方doc部分
mytemplate = Template(filename='/docs/mytmpl.txt') print mytemplate.render()
还可以从设置模板为文件,设置filename属性
mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules') print mytemplate.render()
文件还可以缓存到某个目录下,下面的/docs/mytmpl.txt会产生一个py:/tmp/mako_modules/docs/mytmpl.txt.py
from mako.lookup import TemplateLookup mylookup = TemplateLookup(directories=['/docs']) mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup)
查找模板,方便统一模板路径使用。
mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules') def serve_template(templatename, **kwargs): mytemplate = mylookup.get_template(templatename) print mytemplate.render(**kwargs)
改良了上面的查找方式
mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace') mytemplate = mylookup.get_template("foo.txt") print mytemplate.render()
设置输出编码,以及编码错误时候处理方式