博客迁移到tinkerer
在11年时,将我的博客从wordpress+mysql换成了django+sqlite,具体可见 将博客从wordpress迁移到django 这篇文章, 在折腾精神的感召下,在12年底我将博客程序又换掉了,这次换成了一个基于 sphinx 静态博客生成器 tinkerer , tinkerer 使用 reStructuredText 作为标记语言,可以生成文章的分类,tag,支持评论和代码高亮,文章评论使用 disqus , 高亮代码使用 Pygments 。
说说为什么使用 tinkerer ,从打算把博客弄成静态站点开始我尝试了很多项目,如 octpress 、 jekyll 、 pelican ,一次偶然的机会在 bitbucket 上发现了 tinkerer ,试用后感觉比较顺手,并且可以使用sphinx的扩展,我比较熟悉 sphinx 和 reStructuredText 的使用,平时就用这两个东西写文档,因此选择了基于 sphinx 的 tinkerer 。我最开始使用的是0.4 beta版还存在一些bug,然后我自己做了一些修改pull给作者,作者很快就接受了我的pull request,并表示感谢,现在1.0版本已经发布,基本上没有比较明显的bug了,只是有一些细节可能不是那么完美,还有一个就是主题很少,目前默认的几款主题,都不是很美观,目前我在移植一款主题。
tinkerer的一些使用经验:
* 自定义博客的侧边栏
这里以创建友情链接的plugin作为例子,复制boilerplate主题目录下recent.html为一个新的文件,如friendslinks.html,然后改成如下这样就可以了:
{#-
boilerplate/friendslinks.html
~~~~~~~~~~~~~~~~~~~~~
Sidebar list of all tags.
:copyright: Copyright 2012 by Iñigo Serna
:license: FreeBSD, see LICENSE file
-#}
<div class="widget">
<h1>Friends links</h1>
<ul>
<li><a href="http://www.qdyongai.cn/?from=jason">龙哥-网站设计</a></li>
<li><a href="http://www.zipeng.info/?from=jason">子鹏-kun的记事本</a></li>
<li><a href="http://www.aaronw.me/?from=jason">王炜-我的技术生活</a></li>
<li><a href="http://cuikai-wh.com/?from=jason">小轰-时光立方</a></li>
</ul>
</div>
这里要注意的是默认的modern5主题是继承于boilerplate这个主题,因此只要修改boilerplate这个主题就可以了
然后在conf.py中加入这个文件的配置
# Add templates to be rendered in sidebar here
html_sidebars = {
"**": ["searchbox.html", "categories.html", "recent.html", "friendslinks.html", "weibo.html"]
}
- 创建一个makefile,使用过 sphinx 的人应该都知道 sphinx 会生成一个 makefile,这样可以直接使用make html就可以生成文档了,tinker没有提供,那么我们可以自己写一个,让我么操作的更加自动化,如下是我 Makefile 示例,大家可以参照下:
all: build commit update
clean:
rm -rf blog/html/
build:
tinker -b
serve:
cd blog/html/ && python -m SimpleHTTPServer
commit:
hg commit ./ -m 'add new post'&&hg push
@echo "Done..."
update:
ssh root@jasonwu.me 'cd /home/admin/jasonwu.me/&&hg pull&&hg update'
这个makefile主要实现了生成文档,在本地起一个http服务器来查看生成的文章效果,提交到bitbucket和更新vps上的博客内容等功能,将这些操作完全的自动化,是不是很方便,大家玩的开心。
使用NGINX+UWSGI来部署Django
关于UWSGI的介绍不多说了,想了解的可以自己去搜,uwsgi性能还蛮不错,我们之前使用的fastcgi方式来跑django,前端用F5做负载均衡,用户数增加后服务器的load很高,但换uwsgi服务器的load下降不少,废话不多说,进入正题。 编译安装nginx,用的nginx-0.8.54,目前最新的stable版本
wget http://nginx.org/download/nginx-0.8.54.tar.gz
tar zxvf nginx-0.8.54.tar.gz
./configure --user=nobody
--group=nobody
--prefix=/usr/local/nginx
--with-http_ssl_module
--http-log-path=/var/log/nginx/access.log
--with-http_gzip_static_module
make&&make install
下面来安装uwsgi
wget http://projects.unbit.it/downloads/uwsgi-0.9.6.5.tar.gz
tar zvxf uwsgi-0.9.6.5.tar.gz
cd uwsgi-0.9.6.5
make -f Makefile.Py26
cp uwsgi /usr/sbin/uwsgi #将uwsgi放到PATH下
下面来说说怎么配置: 新建一个uwsgi.xml的文件放到django的目录下
#cat uwsgi.xml
<uwsgi>
<socket>0.0.0.0:8000</socket>
<listen>204800</listen>
<!-- 开启32个线程 -->
<processes>32</processes>
<max-requests>2048000</max-requests>
<buffer-size>8192</buffer-size>
<!-- 你的配置文件 -->
<module>django_wsgi</module>
<profiler>true</profiler>
<enable-threads>true</enable-threads>
<!-- 限制内存空间256M -->
<limit-as>256</limit-as>
<!-- 使用async模式来运行,这里要注意一下,如果你的app的是no-async-friendly 那就不要用这个模式 -->
<async>10</async>
<disable-logging/>
<daemonize>/home/app01/uwsgi.log</daemonize>
</uwsgi>
#cat django_wsgi.py
import os
import django.core.handlers.wsgi
os.environ['DJANGO_SETTINGS_MODULE'] = 'your settings'
application = django.core.handlers.wsgi.WSGIHandler()
下面是nginx的配置:
server {
listen 80;
server_name jasonwu.me;
access_log /var/log/jasownu.me/access_log;
location / {
root /home/app01/;
uwsgi_pass 127.0.0.1:8000;
include uwsgi_params;
}
}
启动服务:
/usr/bin/uwsgi -x /home/app01/uwsgi.xml
/usr/local/nginx/sbin/nginx
这样部署完成了
下面来说说遇到的一个问题,不知道大家有没有遇到, 在我们启动uwsgi后在uwsgi的日志中会出现如下的信息:
– unavailable modifier requested: 1 –
– unavailable modifier requested: 1 –
表现的现象就是启动一段时间没法访问app,在查看uwsgi的源代码中我们找到打印这部份日志的段落,正常情况下应该返回的-1,目前还在查找这个出现这个错误的原因。
参考
- uwsgi的官方wiki: http://projects.unbit.it/uwsgi/wiki/TitleIndex
- Programming in Python with Medusa and the Async Sockets Library: http://www.nightmare.com/medusa/programming.html
unp读书笔记(第六章I/O模型)
在看了unp后才发现自己之前的认识一直都是错误的,把阻塞I/O,非阻塞I/O,同步和异步混为一谈,之前一直觉得异步就是非阻塞io,同步就是阻塞io,主要搞清楚了,五种I/O模型的实现,以及epoll并不是aio,这两个并不是一个东西。
实际上unix有五种I/O模型:
- 阻塞I/O
- 非阻塞I/O
- I/O复用(select和poll)
- 信号驱动I/O(SIGIO)
- 异步I/O
一个输入操作一般有两个不同的阶段: 1. 等待数据准备好 2. 从内核到进程拷贝数据 对于一个套接口上的输入操作,第一步一般是等待数据到达网络,当分组到达时,它被拷贝到内核中的某个缓冲区,第二步是将数据从内核缓冲区拷贝到应用缓冲区。
1.阻塞I/O模型
最流行的I/O模型是阻塞I/O模型,缺省时,所有套接口都是阻塞的。
2. 非阻塞I/O模型
前三次调用recvfrom时仍无数据返回,因此内核立即返回一个EWOULDBLOCK错误。第四次调用recvfrom时,数据已经准备好,被拷贝到应用缓冲区,recvfrom返回成功指示,接着就是我们处理数据。当一个应用进程像这样对一个非阻塞描述字循环调用recvfrom时,我们称此过程为轮询(polling)。应用进程连续不断地查询内核,看看某操作是否准备好,这对cpu时间是极大的浪费,但这种模型只是偶尔才遇到,一般是在只专门提供某种功能的系统中才有。
3. I/O复用模型
有了I/O复用,我们就可以调用select或poll,在这两个系统调用中的某一个上阻塞,而不是阻塞于真正的I/O系统调用。如图6.3,我们阻塞于select调用,等待数据报套接口可读。当select返回套接口可读条件时,我们调用recvfrom将数据报拷贝到应用缓冲区中。使用select的好处在于我们可以等待多个描述字准备好。
4. 信号驱动I/O模型
我们也可以用信号,让内核在描述字准备好时,用信号SIGIO通知我们,我们将此方法称为信号驱动I/O,如图6.4 首先我们允许套接口进行信号驱动IO,并通过系统调用sigaction安装一个信号处理程序。此系统调用立即返回,进程继续工作,它是非阻塞的。当数据报准备好被读时,就为该进程生成一个SIGIO信号。我们随即可以在信号处理程序中调用recvfrom来读数据报,并通知主循环数据已准备好被处理。也可以通知主循环,让它来读数据报。无论我们如何处理SIGIO信号,这种模型的好处是当等待数据报到达时,可以不阻塞。主循环可以继续执行,只是等待信号处理程序的通知,或者数据已准备好处理,或者数据报已准备好被读。
5. 异步I/O模型
异步IO是POSIX实时扩展,我们让内核启动操作,并在整个操作完成后(包括将数据从内核拷贝到我们自己的缓冲区)通知我们。这种模型没有广泛使用。这种模型与前一节介绍的信号驱动模型的主要区别在于:信号驱动I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。我们调用函数aio_read(POSIX异步I/O函数以aio_或者lio_开头),给内核传递描述字,缓冲区指针,缓冲区大小(与read相同的三个参数),文件偏移(与lseek类似),并告诉内核当前整个操作完成是如何通知我们。此系统调用立即返回,我们的进程不阻塞于等待I/O操作的完成。在此例子中,我们假设要求内核在操作完成时生成一个信号,此信号直到数据已拷贝到应用缓冲区才生成,这一点是与信号驱动I/O模型不同的。
6. 五种不同I/O模型的比较
7. 同步I/O与异步I/O
POSIX定义这两个术语如下: 同步I/O操作引起请求进程阻塞,直到I/O操作完成。 异步I/O操作不引起请求进程阻塞。 根据上述定义,我们的前四个模型–阻塞I/O模型,非阻塞I/O模型,I/O复用模型和信号驱动I/O模型都是同步I/O模型,因为真正的I/O操作(recvfrom)阻塞进程,只有异步I/O模型与异步I/O的定义相匹配。
Python : 什么是*args和**kwargs?
def foo(*args, **kwargs):
print 'args = ', args
print 'kwargs = ', kwargs
print '---------------------------------------'
if __name__ == '__main__':
foo(1,2,3,4)
foo(a=1,b=2,c=3)
foo(1,2,3,4, a=1,b=2,c=3)
foo('a', 1, None, a=1, b='2', c=3)
输出结果如下:
| args = (1, 2, 3, 4)
| kwargs = {}
| ---------------------------------------
| args = ()
| kwargs = {'a': 1, 'c': 3, 'b': 2}
| ---------------------------------------
| args = (1, 2, 3, 4)
| kwargs = {'a': 1, 'c': 3, 'b': 2}
| ---------------------------------------
| args = ('a', 1, None)
| kwargs = {'a': 1, 'c': 3, 'b': '2'}
| ---------------------------------------
可以看到,这两个是python中的可变参数。 *args 表示任何多个无名参数,它是一个tuple; **kwargs 表示关键字参数,它是一个dict。并且同时使用 *args 和 **kwargs 时,必须 *args 参数列要在 **kwargs 前,像foo(a=1, b=‘2’, c=3, a’, 1, None, )这样调用的话,会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。
呵呵,知道 *args 和 **kwargs 是什么了吧。还有一个很漂亮的用法,就是创建字典:
def kw_dict(**kwargs):
return kwargs
print kw_dict(a=1,b=2,c=3) == {'a':1, 'b':2, 'c':3}
其实python中就带有dict类,使用dict(a=1,b=2,c=3)即可创建一个字典了。
另:连接两个字典的方法:
第一种:
>>> a={'a':'a','b':'b'}
>>> m=dict(c='c',**a)
>>> m
{'a': 'a', 'c': 'c', 'b': 'b'}
>>>
第二种:
>>> a={'a':'a','b':'b'}
>>> m={'c':'c'}
>>> m.update(a)
>>> m
{'a': 'a', 'c': 'c', 'b': 'b'}
CENT OS安装cx_Oracle遇到的问题及解决方法
这个是 cx_Oracle 的说明链接http://cx-oracle.sourceforge.net/README.txt,我是采用源码安装 安装过程:
wget http://prdownloads.sourceforge.net/cx-oracle/cx_Oracle-5.0.3.tar.gz?download
tar zxvf cx_Oracle-5.0.3.tar.gz
cd cx_Oracle-5.0.3
python setup.py build
python setup.py install
下面是检查它是否可以用
>>> import cx_Oracle
接着出现了两个错误,错误信息如下:
/usr/local/lib/python2.6/site-packages/cx_Oracle-5.0.3-py2.6-linux-x86_64.egg/cx_Oracle.py:3:
UserWarning: Module cx_Oracle was already imported from /usr/local/lib/python2.6/site-packages
/cx_Oracle-5.0.3-py2.6-linux-x86_64.egg/cx_Oracle.pyc,
but /usr/local/cx_Oracle-5.0.3 is being added to sys.path
ImportError: libclntsh.so.10.1: cannot open shared object file: No such file or directory
下面来说说这两个错误的解决方法, 第一个问题,提示说/usr/local/cx_Oracle-5.0.3已经加入到python的 sys.path 里面了 那么我们就在 sys.path 中去掉这个路径: 具体方法
>>> import sys
>>> sys.path
['', '/usr/local/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg',
'/usr/local/lib/python2.6/site-packages/fudge-0.9.4-py2.6.egg',
'/usr/local/lib/python2.6/site-packages/python_memcached-1.45-py2.6.egg',
'/usr/local/lib/python2.6/site-packages/MySQL_python-1.2.3c1-py2.6-linux-x86_64.egg',
'/usr/local/lib/python2.6/site-packages/flup-1.0.3.dev_20100525-py2.6.egg',
'/usr/local/lib/python2.6/site-packages/regex-0.1.20100706.1-py2.6-linux-x86_64.egg',
'/usr/local/lib/python2.6/site-packages/cx_Oracle-5.0.3-py2.6-linux-x86_64.egg',
'/usr/local/lib/python26.zip', '/usr/local/lib/python2.6', '/usr/local/lib/python2.6/plat-linux2',
'/usr/local/lib/python2.6/lib-tk', '/usr/local/lib/python2.6/lib-old',
'/usr/local/lib/python2.6/lib-dynload', '/usr/local/lib/python2.6/site-packages',
'/usr/local/lib/python2.6/site-packages/PIL', '/usr/local/cx_Oracle-5.0.3']
>>> sys.path.remove(r'/usr/local/cx_Oracle-5.0.3')
第一个问题解决,接着第二个问题,这个网上有解决方案,下面说说解决方法: 这个的原因是 Oracle 的路径没有设定
locate libclntsh.so.10.1
/opt/oracle/product/10.2/db_1/lib/libclntsh.so.10.1
/opt/oracle/product/10.2/db_1/lib32/libclntsh.so.10.1
echo /opt/oracle/product/10.2/db_1/lib/ >> /etc/ld.so.conf
ldconfig
就这样第二个问题解决 再试一下:
>>> import cx_Oracle
>>>