车百科SAE升级Bottle.v0.11手记

为什么要升级到Bottle v0.11

说明:事实上Bottle官方发布的最新版本是发布于2012-02-11的v0.10.9,开发中的Bottle版本的称呼是dev,并不存在v0.11这个概念。本文中我借用v0.11来称呼当前的dev,只是因为个人认为v0.11可能很快会发布,不是为了抢沙发进行的SEO,特此澄清。

为什么要使用Bottle

在回答“为什么要升级到Bottle v0.11”之前先回答为什么要使用Bottle。

web2py是我最常使用的Python Web开发框架,它具有开发、部署简单、高效的特点。web2py+SQLite的组合应该是最适合个人站长的解决方案,一个Web应用或网站,包括数据在内,用几分钟就可以完全从一个服务器迁移到另一个服务器上。有了web2py,习惯于“租房”的草根站长们,再也没有“搬家”的烦恼了。

然而由于SAE本身具有的一些限制,目前的web2py还不能直接部署在SAE上,经过SAE工程师和网友们一段时间的努力之后也只能实现最简单的web2py应用在SAE上的部署,还不具备实用价值。

但是对于草根开发者而言,SAE的吸引力可以说是致命的。在云计算和移动互联网时代,一个不需要维护、速度快、高负载、低成本的服务器环境,对于一个Web应用或网站的快速成长具有重要的意义。SAE的出现使开发者将可以把主要精力放在产品设计、程序开发、产品运营和优化升级上,解决了开发者的后顾之忧。更何况,存储、邮件、短信、地理信息、中文分词等服务的使用,可以让Web应用或网站的能力大大提高,却几乎没有增加什么成本。

Bottle是一个单文件的Python Web开发框架,简洁、上手快、应用广泛,SAE支持Bottle是情理之中的事情。Bottle同样内置了一个轻量级Web服务器,本地的开发调试和web2py一样轻松。因此在SAE上进行开发,Bottle是一个不错的选择。

为什么要升级到v0.11

在明白了为什么要使用Bottle之后,接下来回答“为什么要升级到Bottle v0.11”。

Bottle v0.11目前还是开发版,但不久之后就会成为稳定版。SAE目前内置的Bottle是v0.9,这个版本至少有一个重要的不足,那就是URL映射的灵活性不够。

受web2py的影响,我习惯于把CSS文件、JS文件和图片分别放在static/css/、static/js/和static/img/目录下。

在Bottle v0.9中,为了实现对这些静态文件的应用,我需要这样写:

@app.route('/static/css/:filename')
def serve_css(filename):
    return static_file(filename , root='static/css')
@app.route('/static/js/:filename')
def serve_js(filename):
    return static_file(filename , root='static/js')
@app.route('/static/img/:filename')
def serve_img(filename):
    return static_file(filename , root='static/img')
@app.route('/static/doc/:filename')
def serve_doc(filename):
    return static_file(filename , root='static/doc')

而在Bottle 0.11中(事实上从0.10开始就是这样),我只需要这样写:

@app.route('/static/')
def serve_static(filename):
    return static_file(filename , root='static')

可以看到v0.11相对于v0.9的改进具有很大的实用价值,因此需要升级到Bottle v0.11。

此外,因为不想很快又写重写本文,因此选择了开发中的v0.11而不是当前的稳定版v0.10。

让Bottle v0.11在SAE上运行

由于SAE对目录读写的限制,Bottle v0.11无法直接在SAE上运行,为了解决这个问题才有了这篇手记。

把车百科从Bottle v0.9升级到v0.11

准备工作

车百科是一个基于SAE和Bottle的简单应用,提供了汽车标志的和相关信息的快速查询,开发过程可以参考“车百科开发手记”。

在升级车百科之前,先备份源代码。我个人通常使用7z这种压缩格式,因为7z的压缩包中文件名都是以Unicode编码保存的,在Windows和Linux环境下切换时,中文文件名不会出现乱码。

升级开发期间,为了不影响现有应用的正常运行,需要新建SAE应用版本4:

$ git branch newbottle
$ git checkout newbottle
$ gvim config.yaml &
version: 4

Bottle Web开发框架的下载:

$ cd ~src/sae/che123
$ wget https://github.com/defnull/bottle/raw/master/bottle.py
$ git add .
$ git commit -m 'Upgrade Bottle to v0.11 which actually means 2012-04-03 dev.'
$ saecloud deploy
Deploying http://4.che123.sinaapp.com

发现问题,解决问题

升级到Bottle v0.11后,我们的应用会报错:

$ lynx http://4.che123.sinaapp.com
Traceback (most recent call last):
  File "/data1/www/htdocs/790/che123/4/index.wsgi" , line 2 , in 
    from index import app
  File "/data1/www/htdocs/790/che123/4/index.py" , line 1 , in 
    from bottle import Bottle , template , static_file , run
  File "/data1/www/htdocs/790/che123/4/bottle.py" , line 38 , in 
    import base64 , cgi , email.utils , functools , hmac , imp , itertools , mimetypes ,\
  File "/usr/local/sae/python/lib/python2.6/subprocess.py" , line 416 , in 
    import fcntl
ImportError: No module named fcntl

错误出在bottle.py文件的38行和39行的import subprocess上,因为subprocess需要fcntl这个模块,而SAE不支持。

Python官方文档中对fcntl模块的说明是:

This module performs file control and I/O control on file descriptors. It is an interface to the fcntl() and ioctl() Unix routines.

Python官方文档中对subprocess模块的说明是:

The subprocess module allows you to spawn new processes , connect to their input/output/error pipes , and obtain their return codes. This module intends to replace several other , older modules and functions , such as: os.system , os.popen.

而在bottle.py中实际使用subprocess的只有第2596行:

p = subprocess.Popen(args , env=environ)

注释掉下列行,并加上新的sys.exit():

sys.exit(0)
#p = subprocess.Popen(args , env=environ)
#while p.poll() is None: # Busy wait...
#    os.utime(lockfile , None) # I am alive!
#    time.sleep(interval)
#if p.poll() != 3:
#    if os.path.exists(lockfile): os.unlink(lockfile)
#    sys.exit(p.poll())

同时别忘了注释掉import subprocess。

$ git commit -am 'Modify bottle.py to comment subprocess.'
$ saecloud deploy
$ lynx http://4.che123.sinaapp.com/

访问正常,问题解决了。

[分享]源代码&开发手记:SAE应用“车百科” (Python + SAE + Bottle + Bootstrap)

车百科”是一个基于SAE Python的简单应用,提供了汽车标图片志大全,并提供了到厂商主页、相关新闻和评论的快速入口。

“车百科”是用Python Web开发框架Bottle开发的,涉及到了控制器、视图和数据库访问。前端使用了Twitter开发的Bootstrap框架,简洁、高效、强大。

汽车标志图片使用SAE Storage存储,管理方便,上传、访问速度都很快。

开发过程中,没有使用SAE默认的SVN版本控制系统,而是使用了Git来管理代码,用saecloud来部署代码。

为了帮助更多的朋友快速掌握基于SAE的Python开发,我把“车百科”的开发手记源代码公开,一方面希望加强和大家的交流、分享,另一方面希望能帮助一些刚接触SAE开发的朋友。

欢迎访问我的微博博客,交流、分享、沟通提高。

在Python中控制中文标题长度的简单方法

Google关键字:python 中文 标题 长度

以web2py为例:

1. 问题

<li><span class=”right”>{{=article.pub_date}}</span>{{=article.title}}</li>

将输出:

海淀驾校新版网上约车系统12月1日起正式运行 2011-11-29

2. 解决方法

<li><span class=”right”>{{=article.pub_date}}</span>{{=article.title.decode(‘utf-8’)[0:18].encode(‘utf-8’)}}</li>

将输出:

海淀驾校新版网上约车系统12月1日起 2011-11-29

3. 原理

一个中文字符的长度等于两个ANSI字符的长度,因此,先把字符串转换为unicode,然后进行截取,再转换为UTF-8,这样就可以避免中英文字符长度不同计算麻烦或截取结果出现乱码(半个汉字)的情况。

桌面不死——PyQt 4.9和SIP 4.13.1发布

在Web应用和手机、平板应用大行其道的今天,桌面程序开发已经很难吸引大家的注意力。不过仍然有这么一些人还在努力为我们提供更好的桌面程序开发工具:

Riverbank Computing Ltd.于2011年12月22日发布了PyQt 4.9,这个版本提供了对Qt 4.8.0的支持,并包含了QtDBus模块。PyQt的上一个版本4.8.6的发布还是在10月25日,这个两次发布间隔将近2个月的时间。

同时发布的还有SIP 4.13.1,没有重大更新。PyQt 4.9依赖于SIP 4.13.1。

官方下载(Windows、Mac OS X、Linux):
http://www.riverbankcomputing.co.uk/software/pyqt/download
http://www.riverbankcomputing.co.uk/software/sip/download

背景资料:

PyQt是跨平台开发框架Qt的Python绑定,支持Windows、Mac OS X和Linux。SIP是创建C和C++库的Python绑定的工具。PyQt依赖于SIP。

PyQt兼有Qt跨平台和Python开发效率高的优点,代码修改后可直接运行,无须等待编译,节省大量开发调试时间。用cx_Freeze可以把PyQt程序打包成可执行文件,同时支持Windows和Linux,在Windows下可以用InnoSetup制作安装程序。PyQt的缺点和Qt一样,就是开发出来的程序体积较大,基本上10MB打底。华图微学公务员考试软件和华图微学公务员面试互动模拟软件都是用PyQt开发的,Windows版可以在华军软件园下载。

使用Subversion和Mercurial同时管理代码的注意事项

最近在SAE Python上做开发,SAE Python目前还只支持Subversion(svn)版本控制,而我常用的是Mercurial(hg)。两者的最大差别是:svn是集控式的版本控制,hg是分布式的版本控制。hg至少有两个好处,一个是命令更简洁,可以使用hg addremove这样的命令;另一个是速度快,不需要和服务器同步,对于网络较慢的环境尤其重要。

于是,同时用Subversion和Mercurial管理代码就成为了理所当然的选择。

一开始想到使用Mercurial插件来实现Subversion的功能,简单查了一下文档,似乎使用起来不那么方便。

后来在豆瓣发帖询问官方能否增加Mercurial支持,网友benmao给出了提示,也就是使用hg archive:
http://www.douban.com/group/topic/23770733/

具体的操作如下:

$ cd local # local为使用hg管理的目录
$ cp -rf ../1/* . # 1为使用svn管理的目录
$ gvim .hgignore & # 设置忽略.svn目录
$ find . -name “.svn” -exec rm -rf {} \; # 删除各个目录下的.svn目录
$ hg addremove # 更新版本库
$ hg commit -m ‘Revision changelog’
$ hg archive ../1
$ cd ../1
$ svn status
$ svn commit -m ‘Rvision changelog’

在hg版本库中删除并忽略.svn目录是很重要的,否则在进行hg archive时会出现类似下面的提示:
中止: Permission denied: ~/src/sae_python/1/static/img/.svn/.entries-7VTD4F
也就是说.svn目录的权限和其它文件是不同的,不忽略的话会带来权限设置方面的额外工作,并且毫无意义。

我的.hgignore文件的内容如下:
~$
.swp$
.bak$
.pyc$
.svn

谨以此文献给在SAE上奋斗的所有Pythoner!

在PyQt中让QTableView的内容居中

QTableView没有直接提供居中文本的方法,需要自己实现,一种解决方案是自定义Delegate。

代码如下:

ID = 0
TYPE = 1
NAME = 3

class CenterDelegate(QItemDelegate):

def __init__(self, parent=None):

QItemDelegate.__init__(self, parent)

def paint(self, painter, option, index):

painter.save()
painter.drawText(option.rect, Qt.AlignCenter, index.data(Qt.DisplayRole).toString())
painter.restore()

class TestDialog(QDialog):

def __init__(self, parent=None):

self.testView.setItemDelegate(CenterDelegate()) # ID和TYPE居中
self.testView.setItemDelegateForColumn(NAME, QItemDelegate()) # NAME不居中

Python Web开发框架Pyramid发布1.1版

著名Python Web开发框架Pyramid今天发布了1.1正式版。Pyramid是Pylons Project的核心产品,Pylons Project由前Pylons Web开发框架和repoze.bfg Web开放框架合并而来。

Pyramid 1.1的主要更新如下:

* 支持request.response属性
* 全新的视图自省(view introspection)特性:paster pviews
* 支持静态路由(static routes)
* 默认的HTTP异常视图
* 用http_cache视图配置参数让Pyramid设置HTTP缓存头
* 新特性使得在Pyramid环境中写脚本更容易

更多的更新内容请参阅官方公告:
http://docs.pylonsproject.org/projects/pyramid/1.1/whatsnew-1.1.html

升级到web2py 1.9.3后出现“500 Internal Server Error”错误

在Web浏览器中访问时,提示“500 Internal Server Error”错误。服务器操作系统是CenOS 5.6,web2py跑在系统自带的Apache上。

在终端下运行“$ python web2py.py”提示:
File “/var/www/html/web2py/gluon/utils.py”, line 98, in <module>
ctokens = initialize_urandom()
File “/var/www/html/web2py/gluon/utils.py”, line 93, in initialize_urandom
logging.warn(
NameError: global name ‘logging’ is not defined

但是“$ sudo python web2py.py”却可以正常运行
尝试重启系统:
$ sudo reboot
还是一样的结果。

直接查看源代码:
[chinakr@softwaretest web2py]$ vim gluon/utils.py
try:
os.urandom(1)
if os.path.exists(‘/dev/urandom’):
open(‘/dev/urandom’,’wb’).write(”.join(chr(t) for t in ctokens))
except:
random.seed(node_id + milliseconds)
logging.warn(

Google“/dev/urandom web2py”找到了答案:
http://www.mail-archive.com/web2py@googlegroups.com/msg65128.html
解决方法:
$ ls -l /dev/urandom
cr–r–r– 1 root root 1, 9 06-06 10:36 /dev/urandom
$ sudo chmod 777 /dev/urandom
$ ls -l /dev/urandom
crwxrwxrwx 1 root root 1, 9 06-06 10:36 /dev/urandom
这样Apache中的web2py就可以正常工作,不再提示“500 Internal Server Error”错误了。

原来web2py 1.96.3中需要使用/dev/urandom来生成web2py_uuid,但是CentOS上apache用户默认情况下没有这个目录的权限,因此造成了Apache中web2py访问错误。

PyQt Programming Style Guide

良好的编程风格能够提高代码的可读性,降低代码维护的成本,是团队开发中必须重视的问题。本文档可用作PyQt桌面开发培训资料。

在线浏览

目录

  • 为什么要重视编程风格
  • 设置Python解释器
  • 文件字符编码
  • 注释
  • docstring
  • import语句
  • 在终端中使用中文字符
  • 一行代码的长度
  • 缩进
  • 空行
  • 空格的使用原则
  • 括号
  • 标识符的命名规则
  • main()函数
  • 参考资料
  • 欢迎加入创业团队

在Windows 7下使用Eric4开发PyQt程序时出现’module’ object has no attribute ‘StackedWidget’错误

作者:chinakr
日期:2011-02-16

软件环境:Windows 7,Eric4,PyQt

在按照Eric4 Python IDE官方网站的MiniBroser tutorial实践时,生成对话框代码的时候会出现’module’ object has no attribute ‘StackedWidget’错误。

通过Google“’module’ object has no attribute ‘StackedWidget’”找到了原因:

使用pyqt4在eric 5 IDE时 出现’module’ object has no attribute ‘StackedWidget’错误的
http://hi.baidu.com/tisiem/blog/item/ce9de9c8a25ce5047e3e6f20.html

原来这是PyQt4的一个Bug!

按照上述文章的提示,找到C:\Python27\lib\site-packages\PyQt4\uic\quparser.py这个文件,在第16行把“StackedWidget“修改为”QStackedWidget“,重启Eric4,再生成对话框代码时就没有’module’ object has no attribute ‘StackedWidget’这个错误提示了!

(欢迎转载,转载请注明作者和出处;chinakr的技术博客:http://blog.quickbest.net)