Aug 2

web.py bottle flask都是使用easy_install安装的,web.py0.34,flask0.6,bottle0.82
打印的页面都是简单的helloworld
—————————————————web.py——————————————————
import web

urls = (
    '/', 'hello'
)
app = web.application(urls, globals())

class hello:       
    def GET(self):
        return 'Hello World!'

if __name__ == "__main__":
    app.run()

—————————————————flask————————————————————
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()
————————————————bottle————————————————————
from bottle import route, run

@route('/')
def index():
    return 'Hello World!'

run(host='localhost', port=8000)
————————————————————————————————————
其中bottle和flask的在firefox3.68上显示效果完全相同,但是web.py不知是什么原因却自动输出了等宽字体(这个只是个人的疑惑,对效率应该没有影响)

介绍一下测试环境 cpu是i5 430m的,然后操作系统是ubuntu10.04 amd64 desktop的,python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
kernel 2.6.32-24-generic,大概就是这么多了
测试工具是apachebench2.3,参数是每个程序测试20次,很简单的测试
直接看输出吧
————————————————————首先是web.py——————————————————
billma@billma-laptop:~$ ab -n 20 http://0.0.0.0:8080/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 0.0.0.0 (be patient).....done


Server Software:        CherryPy/3.1.2
Server Hostname:        0.0.0.0
Server Port:            8080

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      1
Time taken for tests:   0.056 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Total transferred:      2080 bytes
HTML transferred:       240 bytes
Requests per second:    357.34 [#/sec] (mean)
Time per request:       2.798 [ms] (mean)
Time per request:       2.798 [ms] (mean, across all concurrent requests)
Transfer rate:          36.29 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     2    3   0.9      2       5
Waiting:        2    3   0.9      2       5
Total:          2    3   0.9      2       5
WARNING: The median and mean for the processing time are not within a normal deviation
        These results are probably not that reliable.
WARNING: The median and mean for the waiting time are not within a normal deviation
        These results are probably not that reliable.
WARNING: The median and mean for the total time are not within a normal deviation
        These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
  50%      2
  66%      3
  75%      3
  80%      3
  90%      5
  95%      5
  98%      5
  99%      5
 100%      5 (longest request)
————————————————————再来flask————————————
billma@billma-laptop:~$ ab -n 20 http://127.0.0.1:5000/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient).....done


Server Software:        Werkzeug/0.6.2
Server Hostname:        127.0.0.1
Server Port:            5000

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      1
Time taken for tests:   0.024 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Total transferred:      3300 bytes
HTML transferred:       240 bytes
Requests per second:    830.77 [#/sec] (mean)
Time per request:       1.204 [ms] (mean)
Time per request:       1.204 [ms] (mean, across all concurrent requests)
Transfer rate:          133.86 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     1    1   0.4      1       2
Waiting:        0    1   0.4      1       2
Total:          1    1   0.5      1       2

Percentage of the requests served within a certain time (ms)
  50%      1
  66%      1
  75%      1
  80%      1
  90%      2
  95%      2
  98%      2
  99%      2
 100%      2 (longest request)
————————————————最后是bottle的——————————————————
billma@billma-laptop:~$ ab -n 20 http://localhost:8000/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done


Server Software:        WSGIServer/0.1
Server Hostname:        localhost
Server Port:            8000

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      1
Time taken for tests:   0.013 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Total transferred:      3300 bytes
HTML transferred:       240 bytes
Requests per second:    1503.31 [#/sec] (mean)
Time per request:       0.665 [ms] (mean)
Time per request:       0.665 [ms] (mean, across all concurrent requests)
Transfer rate:          242.23 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       0
Processing:     0    1   0.2      0       1
Waiting:        0    0   0.2      0       0
Total:          0    1   0.3      1       1
ERROR: The median and mean for the processing time are more than twice the standard
       deviation apart. These results are NOT reliable.

Percentage of the requests served within a certain time (ms)
  50%      1
  66%      1
  75%      1
  80%      1
  90%      1
  95%      1
  98%      1
  99%      1
 100%      1 (longest request)

就是这样了,可以看出,bottle已经把另外两个微框架拉的很远了,另外,我还用fapws3+bottle做了测试,结果是0.009s,这样成绩直接秒杀其他的框架了……

Jul 21

项目介绍
Exaile-cn是一个对Exaile进行扩展的项目,通过对Exaile进行扩展,使Exaile功能上更加丰富,更加符合中国用户的使用习惯,给国内Linuxer提供一个更加本土化的播放器.

安装方法
注意:Exaile-cn现在只支持Exaile0.3.2.0,如果你的Exaile不是0.3.2.0,可能会无法正常使用。
先运行whereis exaile,查找exaile的位置,下面假设exaile位于/usr/lib/exaile/下
1.解决乱码问题方法:将_id3.py覆盖到/usr/lib/exaile/xl/metadata目录下(需要root权限)
2.豆瓣封面插件安装方法:将doubancovers复制到~/.local/share/exaile/plugins/(如果没有目录,先创建目录)下,然后启动exaile,选中插件选项即可
3.歌词同步显示插件安装方法:先把engine_unified.py和engine_normal.py覆盖到/usr/lib/exaile/xl/player,再将LyricDisp目录复制到~/.local/share/exaile/plugins下,然后启动Exaile,选中插件选项即可
4.面板标签竖行显示:将__init__.py覆盖到/usr/lib/exaile/xlgui/目录下(需要root权限)
5.豆瓣电台插件安装方法:将track.py覆盖到/usr/lib/exaile/xl/trax/目录下(需要root权限),将doubanfm复制到~/.local/share/exaile/plugins/,启动exaile,选中插件选项,然后在Douban.FM插件的设置里面填写用户名和密码,重启exaile,在文件菜单里面会显示豆瓣电台列表

更新说明
10.7.21
增加豆瓣电台插件
改进歌词滚动显示
支持歌词文件名的自定义
支持调整歌词行距
支持exaile0.3.2
增加透明度设置
10.4.2
支持Exaile0.3.1.0
增加了面板模式显示歌词方式
增加了面板标签竖行显示补丁
增加了手动搜索歌词选项
增加了搜狗歌词服务器
10.1.1
添加了修改过的__init__.py,解决issue 7
09.12.31
修复了播放音乐时无法启用歌词插件的bug
修改了歌词文件分析方式,解决无法正确读取一行歌词有多个时间标签的歌词的bug
修复了不能保存歌词修改的bug
添加了歌词插件透明度、歌词目录、歌词颜色的选项

下载 :http://exaile-cn.googlecode.com/files/exaile-cn100721.tar.gz

Jun 7

正在实现歌词滚动,初步的想法是现有一个layout,然后在上面放上一个vbox,这样vbox就可以自由移动了,然后根据歌词行数在vbox上放一些label……有几行放几个

在歌曲播放的时候根据当前歌词所在的行的位置调整vbox的位置……大概的思路就是这样

实现起来不是很困难,不过却被另一个问题给难住了……

我想让当前歌词行实现不同的颜色,这不难,难的是怎么把变过色的label恢复回以前的颜色,这个直接悲剧了,不能清一色都恢复成黑色,因为如果gtk使用的皮肤也是黑色的话就悲剧到什么也看不出来了……

目前还没有想到好的解决办法,很操蛋,主要是到现在也没看到可以获取当前文字颜色的方法………………………………我靠

只能是把背景改成黑色的了,千千静听不也是这样写的吗……

 

Feb 19

其实也是一个很小的应用,需要借助js代码高亮脚本,可以到http://alexgorbatchev.com/wiki/SyntaxHighlighter:Download去下载

下载完,解压到一个新建的目录里面,然后新建一个core.py

 

#!/usr/bin/env python
import cgi
import datetime
import wsgiref.handlers

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp

Out ="""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Your code</title>
	<script type="text/javascript" src="scripts/shCore.js"></script>
	<script type="text/javascript" src="scripts/shBrushBash.js"></script>
	<script type="text/javascript" src="scripts/shBrushCpp.js"></script>
	<script type="text/javascript" src="scripts/shBrushCSharp.js"></script>
	<script type="text/javascript" src="scripts/shBrushCss.js"></script>
	<script type="text/javascript" src="scripts/shBrushDelphi.js"></script>
	<script type="text/javascript" src="scripts/shBrushDiff.js"></script>
	<script type="text/javascript" src="scripts/shBrushGroovy.js"></script>
	<script type="text/javascript" src="scripts/shBrushJava.js"></script>
	<script type="text/javascript" src="scripts/shBrushJScript.js"></script>
	<script type="text/javascript" src="scripts/shBrushPhp.js"></script>
	<script type="text/javascript" src="scripts/shBrushPlain.js"></script>
	<script type="text/javascript" src="scripts/shBrushPython.js"></script>
	<script type="text/javascript" src="scripts/shBrushRuby.js"></script>
	<script type="text/javascript" src="scripts/shBrushScala.js"></script>
	<script type="text/javascript" src="scripts/shBrushSql.js"></script>
	<script type="text/javascript" src="scripts/shBrushVb.js"></script>
	<script type="text/javascript" src="scripts/shBrushXml.js"></script>
	<link type="text/css" rel="stylesheet" href="styles/shCore.css"/>
	<link type="text/css" rel="stylesheet" href="styles/shThemeDefault.css"/>
	<script type="text/javascript">
		SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf';
		SyntaxHighlighter.all();
	</script>
</head>

<body >
<h1>Here is your Code</h1>
<p>Good Luck!</p>

<pre class="brush: %s;">
%s
</pre>
</html>
"""


class CodeStr(db.Model):
  content = db.TextProperty()
  date = db.DateTimeProperty(auto_now_add=True)
  lang = db.StringProperty(multiline=False)

class InputCode(webapp.RequestHandler):
  def get(self):
    self.response.out.write('<html><body>')
    self.response.out.write('Code:')

    self.response.out.write("""<form action="/sc" method="post">
                                    <div><select size="4" id= "lang" name="lang">
                                        <option>python</option>
                                        <option>js</option>
                                        <option>xml</option>
                                        <option>bash</option>
                                    </select></div>
                                    <div><textarea name="content" rows="8" cols="70"></textarea></div>
                                    <div><input type="submit" value="Submit"></div>
                                </form>
                            </body>""")


class SaveCode(webapp.RequestHandler):
  def post(self):
    self.code = CodeStr()
    self.code.content = self.request.get('content')
    self.code.lang = self.request.get('lang')
    self.code.put()
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Your code\'s ID is %s\n' % self.code.key().id())
    self.response.out.write('You can visit http://billgaesh.appspot.com/o?id=%s to get your code\n' % self.code.key().id())
    self.response.out.write('Good Luck')
  def get(self):
    self.response.out.write('Sorry This doesn\'t work!')

class OutCode(webapp.RequestHandler):
  def get(self):
    global Out
    id = self.request.get('id')
    key = db.Key.from_path("CodeStr", int(id))
    query = CodeStr.all()
    query.ancestor(key)
    code = query.get()
    s = code.content.replace('<', '&lt;').replace('>', '&gt;')
    O = Out % (code.lang, s)
    self.response.out.write(O)

application = webapp.WSGIApplication([
  ('/i', InputCode),
  ('/sc', SaveCode),
  ('/o', OutCode)
], debug=True)

def main():
  wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
  main()


在新建一个叫app.yaml的文件

 

application: *
version: 13
runtime: python
api_version: 1

handlers:
- url: /i
  script: core.py

- url: /sc
  script: core.py

- url: /o
  script: core.py

- url: /src
  static_dir: src

- url: /scripts
  static_dir: scripts

- url: /styles
  static_dir: styles

- url: /
  static_files: test.html
  upload: test.html

 

 

把其中的

application: *

改成你自己注册的app名称,然后用GAE SDK上传到GAE的服务器上就可以了

在 http://*.appspot.com/i 里面输入代码,然后会给你一个ID,在http://*.appspot.com/o?id=** 里面就可以看到你的代码了

目前还比较垃圾,如果不满意的话,可以自行修改以下

http://billgaesh.appspot.com/i 是我的代码贴地址,欢迎使用

目前已知的BUG是如果代码中有“”“,可能会跨站……

Feb 17

说一下下一步的计划:

1.OSD模式

2.Panel模式

3.多歌词引擎

4.完善歌词搜索方法

5.添加手动搜索

6.歌词调节

7.做啥

Feb 16

                                        ’沧浪之水清兮,可以濯吾缨;沧浪之水浊兮,可以濯吾足‘——《渔夫》

    Exaile-cn忙活了很长时间了,花了很大的功夫,下了很大的力气。现在程序写得差不多了,功能上基本上没什么可以再往上加的了,让人感觉很迷茫,不知道该再为这个小小的项目做些什么……挺无奈的,这种感觉……恩,真的是有点不知所措了。

    目前看来,实际上真正需要的功能是不多的,而现在基本上都实现过了,效果还都不错,以后该做些什么,真的不知道了……

    现在的学习压力也愈来愈大,有时候会有放弃项目的冲动……

    我的能力实在有限,有些功能可以说是心有余,力不足啊,要学习python,pygtk,pango,cario实在是时间,精力有限,没有办法,要把所有的东西都掌握是个很长的时间,还要找bug,写patch,真的很累……

Jan 17

今天写了近两个小时的代码,是关于鼠标滑轮滚动调整歌词的功能,进展非常之不顺利……太不顺利了……

一开始先goooooogle了一番鼠标event,找到了一个叫scroll-event的,ms相当好用,具体用法可以参考这个:http://zuosa.net/9nha.u

最初设想把event挂到window上就可以了,但是写出代码后发现并不成功,当鼠标是在label上滚动滑轮时,没有任何反应……

也不知道是为什么,就开始盲目处理,处理了好半天,都是原地踏步了……没有任何进展,后来想起了,这是因为label并不能发event的缘故……具体情况可参见pygtk教程,必须要配合eventbox使用

费了老半天去修改界面文件,把所有的label都换成eventbox,然后再在eventbox上加label,够麻烦的

完成了这步,又有了新问题——接到事件后该如何响应……迷茫了,最后马马虎虎写了一段不上去,算是能用了

本来是想通过调歌词来调时间的,可是这样不能实现,因为歌词是精确到毫秒的,可是exaile的seek功能只能精确到秒……无奈

所有只能是通过调时间来调歌词,可这样效果就大减了,不管怎么样,总算又写了一些代码……

Jan 16

一直想写个这样的程序,可苦于自己对于这个GAE一窍不通……所以一直也没下手写,今天终于写了一个,其实也十分简单,参照了一下网上的一个些用pyfetion收天气的方法

最关键的是这一部分(虽然很短)

monitor.py

#! /usr/bin/python
#coding=utf-8

import re
from google.appengine.api import mail
from google.appengine.api import urlfetch

wap = urlfetch.fetch('http://m.baidu.com/tq?area=%E5%9E%A6%E5%88%A9').content
Tomorrow = re.findall(r'明\:.*?<',wap)[0][:-1]

mail.send_mail(sender="******@gmail.com", to="******@139.com", subject="Weather", body=Tomorrow)

最初,因为不了解gae的详细用法,先写了一个通用版

 

#! /usr/bin/python

import urllib,re
import email,smtplib,time

wap = urllib.urlopen('http://m.baidu.com/tq?area=%E5%9E%A6%E5%88%A9').read().decode('utf-8') #网页视情况而定
Tomorrow = re.findall(r'明\:.*?<'.decode('gbk'),wap)[0][:-1]

msg = email.Message.Message()
msg['to']='billnowar@139.com'
msg['from']='billnowar@163.com'
msg['date']=time.ctime()
msg['subject']=email.Header.Header('weather','gb2312')
body=email.MIMEText.MIMEText(Tomorrow.encode('gb2312'),_subtype='plain',_charset='gb2312')

server=smtplib.SMTP('smtp server')
server.login('username','password')
server.sendmail(msg['from'],msg['to'],msg.as_string()[:-1]+body.as_string())

这上面这个是用python自带的库写的,学习了以下email和smtplib后很快就告成的版本

接下来就不容易了,我把email和smtplib、urllib改成了from google.appengine.api import mail和from google.appengine.api import urlfetch这两个……(因为不知到email和smtplib、urllib能不能用……)

然后又出现了编码问题……我不知道gae上到底该用utf-8还是别的什么,而且我也不清楚我手机是用什么编码(这个最麻烦)……

经过实验,发现根本不用改编码,全部都用utf8即可,百度天气是utf-8,所以省去了很多不必要的代码

忙活了两个多小时,终于还是让我搞成了!

通过写这个程序,初步了解了一下gae的机制:

1.GAE貌似可以使用所有的python自带库,既然re可以,那么其他的库理应也可以,这个没有实验,但是猜想应该是可以

2.GAE的cron,掌握了cron的基本写法,先写间隔 再写周期 再写具体时间

3.GAE编码用utf-8,这个实际有点废话……

4.GAE的google.appengine.api.mail.send_mail的sender参数应该添你的gmail邮箱,负责无法使用……

Jan 3

最近几天一直在下小雪,很小很小的,基本上只是给地面铺上了一层白纱,但是感觉很温暖。

理发

老爸坚持让我在上次的那个理发店理,说那里理得不错,可是理完了他又不满意……

眼镜

徘徊过许久之后终于换了眼睛,黑框的,从没戴过这种,(很丑,没脸见人了)

Exaile-cn

091231发布之后基本上很失败,虽然确实需要的人不多,但也不至于如此失败……

博客

博客确实是个麻烦事儿,总找不到好的……换了又换

成绩

第三次月考,成绩惊人的差,大跌眼镜……还有一个月,努力吧,一定要用这个月的时间努力了

 

Jul 21

了解了TX最新发布的东厂补丁后,对TX彻底失望了,再见吧,以后我不会再使用任何tx的工具了……
想联系我的话,Email:billnowar@gmail.com,或gtalk上 我,我的blog :http://billma.yo2.cn