2012年10月23日星期二

Eval is evil

PyYAML读取Puppet的YAML文件,会从中提取出一个ruby变量,成为Python的datetime模块定义的datetime对象。转换为JSON时会出错,因为JSON不知道怎么处理datetime对象。

试了用repr先处理这个对象,即可转换为JSON,在Django中处理时再eval,就可原样返回之前的datetime对象。这样做很方便,无需知道对象的具体类型。但是太不安全了,因为没有内容判断,把从文件中得到的任何东西都进行eval。测试的时候可以eval,实际代码中是用datetime类的strftimestrptime函数配对转换的。

2012年10月21日星期日

Django项目的路径设置

一个别人的Django项目,在命令行用manage.py启动是正常的,但在Eclipse里启动后却出错,页面显示找不到django-session表。发现是找不到SQLite数据库文件的原因。可以看出,django-session是Django进程访问的第一个表,以后如果碰到这个错误,那么一定是数据库配置的问题。

新建PyDev Django项目时,会有对话框来设置项目,包括数据库类型和库名。对于目录里已有相关文件的项目,这个设置是无效果的,该设置是为了给新建项目生成settings.py。出错开始,我还以为需要改正在这个对话框提供过的设置,就在项目属性里找相关的设置,但找不到。其实所有Django相关的设置都在settings.py里面。

settings.py里面,SQLite数据库文件是直接写的文件名,这就是个相对路径,相对于Django进程的工作目录,即getcwd(3)的结果。如果不是从项目根目录启动manage.py(假设settings.pymanage.py都在根目录),那就找不到数据库文件,因为在PyDev里面启动Django时,进程工作目录是Eclipse的Workspace所在目录。
所以不要提供相对路径,而应该使用“动态的绝对路径”。在settings.py的开头写入:
import os.path
ROOT = os.path.dirname(os.path.abspath(__file__))
这样ROOT就是settings.py文件所在目录,根据ROOT来指定项目文件的目录,包括SQLite数据库文件、静态文件等,不论从哪里启动项目,文件都可以找到。

2012年10月6日星期六

自动挂载存储卡的问题

弄了一个4GB的Micro SD卡,可以把手机上2GB的升级了。把手机用USB存储模式连接到电脑,SD卡没有自动挂载,就用mount /dev/sdb1 /mnt挂载了,然后用tar把卡上的内容打包。把新卡换到手机上,再用tar把打包的内容释放到新卡上,但是发现原来的中文文件名字,在压缩包里面显示的是一串问号?,导致解压失败。

因为存储卡是VFAT文件系统的,想起默认的mount会有编码问题,但是懒得查mount选项了,就想搞定自动挂载,因为Ubuntu会对VFAT的移动设备自动挂载,会设置一系列参数,不会出现编码问题。

在Ubuntu的官方文档看到自动挂载udisks实现的,我只好手动试试:
/usr/bin/udisks --mount /dev/sdb1
结果出错,说是
Mount failed: Error mounting: mount exited with exit code 1: helper failed with:
mount: only root can mount /dev/sdb1 on /mnt/pi
看到那个/mnt/pi就知道原来是我在fstab文件里面写了/dev/sdb1的条目,所以udisks没有自动挂载,把这个条目注释后,就可以自动挂载了,而且也没有文件名乱码了。自动挂载的参数是:
/dev/sdb1 on /media/595B-BB30 type vfat (rw,nosuid,nodev,uid=1000,gid=1000,shortname=mixed,dmask=0077,utf8=1,showexec,flush,uhelper=udisks)
自动挂载设定了好多有用的参数,比手动挂载方便多了,utf8=1应该就是处理编码问题的选项。