Explore. Dream. Discover.

Samuel Chen's life

Twenty years from now you will be more disappointed by
the things that you didn't do than by the ones you did do.
So throw off the bowlines. Sail away from the safe harbor.
Catch the trade winds in your sails.

Explore. Dream. Discover.
—— Mark Twain

2011年4月15日星期五

python 的编码,关于 encode, decode 的简单原则

Python 中 encoding 的处理其实已经很简单了,根据我这近一个月来用python的经验,有一个简单的原则可以作为参考。

基于python 2.7
1. 类型要清楚, unicode 不是 str
2. decode 之后的结果都是 unicode
3. encode 之后的结果都是 str,其编码是你encode的参数
4. 输出一律用 str
5. 存取一律用 unicode

 就这么简单,编码基本上就不会错了。 
举个例子,有个GBK编码的文件 name.txt,每行一个人名

for line in open('name.txt').readlines():
    print line  # 这时候 line 都是 gbk 的 str 
    x = line.decode('gbk')  # 转成 unicode了 >> 建议这么做, 原则: 但凡输入的,一律转换成unicode后处理
    print x  # 输出 unicode >> 不建议这么做
    print x.encode('utf-8') # 输出 str >> 建议这么做,原则:但凡输出,一定编码成str
    store_to_db(x)   # 这时候存的都是unicode
    my_str = x.encode('big5') # 转成 big5了
    print m_str   # 输出的是 big5 的 str

此外,encode 的时候不一定会成功,这时候会raise一个exception,这是因为 encode 还有一个参数用来控制encode失败后的处理,default是strict,也就是抛异常。

你可以用 encode(src, 'replace') 来处理,replace就表示碰到转不了的,用问号'?'来代替,而不是抛异常。

具体用法,查文档。

同样,输出的时候,输出流也需要有编码。比如stdout默认是ascii的,而你要输出unicode,就需要得到一个基于unicode的输出流,output = codecs.getwriter('utf-8')(sys.stdout)


标签: ,

2011年4月2日星期六

web.py 在 apache + fastcgi 配置 tips

根据web.py官网的说明,配置使其运行在apache + fastcgi 上,碰到了许多问题,耗了两天时间才整明白。一方面是apache的配置不熟悉,另外一方面是其官方文档也有些疏漏,问题及解决办法如下(ubuntu 10.04):
  • 调试日志
    web.py 应用挂在服务器上以后,stdout/stderr,都好像转了(查网上的,未验证),另外apache的用户是www-data,用户当前目录也是没有权限,所以logging要记录在/tmp下,或者单独建一个/log目录给写权限才行,这个一般规划好了没什么问题。
    另外,也可以做个ApacheLogHandler来将日志记到apache的日志文件中,这个网上可以搜到。
    然后就是,apache的日志文件在/var/log/apache2/ 。如果你的网站配置文件修改了日志位置,要注意这个地方只记录了一部分,还有一些仍然会记录在default位置。
    最后,可以使用traceback包来记录未处理的异常,代码如下:
    
    try:
        # web.py code
        # urls = ...
        # ...
        # app.run()
    
    except Exception, e:
        f = None
        if os.name == 'posix':
            f = open('/tmp/yule_unhandled_error.log', 'w')
        else:
            f = open('%s/yule_unhandled_error.log' % os.environ['temp'], 'w')
        traceback.print_exc( file=f )
        traceback.print_exc( file=f )
        f.close()
    
    
  • python 库路径 (PYTHONPATH)
    在 apache + fastcgi 中运行 python cgi,如果你使用了 PYTHONPATH 来引用库,你会发行看到的永远是 500 Internal Error。这是因为apache没有复制shell中的环境变量。
    注意,不要使用envvar文件,或者在网站配置文件中用setEnv,passEnv 等方法,这些方法我试过完全没有用。
    你要做的是,用代码将所有的路径全部都加到sys.path中。代码如下:
    
        import os, sys
        python_path = "/you/python/lib/path:/you/python/lib/path2".split(':')
        for path in python_path:
            sys.path.insert(0, path)
    
    
    当然你可以检查path是否已经加入了,注意路径访问权限,牢记现在的用户是www-data。
  • 静态文件
    好了,现在都配好了,再访问网站 ... OK 出来了!
    等等! 怎么搞的,样式表,图像怎么都显示不出来了?
    原来是web.py 官网的配置文件有少许疏漏,静态文件的转发不对!
    假设静态目录是网站根下的 /static/ (这也是web.py的推荐位置),那么我们要做的是修改网站配置文件的mod_rewrite 规则为:
    
    
        # 修改 ifmodule 这一节,注意蓝色行
           RewriteEngine on
           RewriteBase /
           RewriteCond %{REQUEST_URI} !^/icons
           RewriteCond %{REQUEST_URI} !^/favicon.ico$
           RewriteCond %{REQUEST_URI} !^/static/  ### 注意这一行 
           RewriteCond %{REQUEST_URI} !^(/.*)+code.py/
           RewriteRule ^(.*)$ code.py/$1 [PT]
    
    
    
好了,现在再试试,是不是已经好了 :)


标签: , , , , ,