青岛度假一周

七月初匆匆忙忙把离校的手续和公司入职需要的材料准备好了,正好公司最近也没什么活要干,就趁着实习结束和正式入职之间的空隙,上周请一个星期的假去毕业旅行,这已经在日程里被推延了很久了。

7月11号从上海坐飞机飞到青岛,炎炎夏日,正是青岛的旅游旺季,有沙滩和海水,可以下海泡澡,还有街边的海鲜烧烤和啤酒。本来毕业旅行想去西安的,但是听朋友说西安夏天太热了,适合秋天去,所以就改去避暑胜地青岛了,但是后来这位西安的朋友过来青岛的时候,却发现青岛比西安要闷,顿时有种被骗的感觉。我们在青岛的一个星期,虽然温度也有30度左右,但是一直都在海边附近玩,一点也不觉得闷,吹过来的海风很凉快,躲在树和房子的影子下,感觉就像是初秋,很舒服,以至于我们16号回到上海的时候,觉得空气闷得要死,简直难以呼吸。

在青岛也没有去太多的地方玩,第一天兴致勃勃的走了几个有名的地方,劈柴院、栈桥、大学路和小鱼山公园,晚上还去奥帆中心那一带吃海鲜自助餐,第二天就已经懒得奔波了,就去了海底世界公园,本以为可以消遣一天,结果其实没什么意思,我们也就走马观花的逛了一圈,增长一些海底生物知识,顺便深入了解了一下餐桌上的海鲜们的学名,其实后来也都忘了。第三天景点也懒得去了,本来就是消遣,不如找个自己喜欢的方式度过,就找了一家比较有特色的咖啡厅,名字叫“不是书店”,看了一下午书,这里既是书店又是咖啡厅,如果点一杯咖啡的话,可以免费借阅里面的书,比较惊喜的是里面有好几本书是之前早就想要拜读的。晚上的时候,一心想要去寻找地道的青岛啤酒屋,走了几家网上推荐得比较多的,发现都好low…,顿时对啤酒屋也没啥渴望了,就找了附近一家人爆满的烧烤摊,在那吃烧烤喝啤酒。第四天我那位西安的朋友过来了,她从遥远的大西北追随爱情来到青岛工作,前一天刚去了公司报道,她知道我们已经吃了好几天的海鲜,早已经吃腻了海鲜,所以请我们吃了一顿丰盛的韩式料理。之后一直到回来,基本上除了咖啡厅和宾馆哪都不去了。

后来总结了一下,我们这一趟算是青岛咖啡厅之旅,5天6夜的旅程,去了四个不同的咖啡厅,最少呆一个小时,最多的呆了三个小时。青岛的咖啡厅真的很多,而且每家咖啡厅的装饰、风格各不相同,窗上的图画手绘、座椅、椅子上的坐垫、桌上的台灯以及吧台的装饰,每一家都是用心布置过的,至少比星巴克那种统一布置出来的显得更花心思,堪称艺术,咖啡的味道大同小异,虽然不会品,但是感觉味道很好,显然是专业学过做咖啡的,至少拉花是做得很漂亮,绝对不是街头饮品店草草做出来的,也不是像肯德基那种机器上按一下就自动做出来的。

比较遗憾的一点是,我们两次想下海游泳都失败,最后只能以留着一些遗憾也是好的来安慰自己,第一次去的时候不知道更衣淋浴室关闭时间,正好错过了,第二次是明知道时间,结果在咖啡厅看书不知不觉就很晚了,过去的时候正好海边浴场又快关闭了。其实更衣淋浴室关闭以后,还是有很多人要么在家里要么在附近饭店里换好衣服下海游泳的,但是我们觉得多少有些不方便,而且海上的救生人员也都下班了,这时候下海也有些不太安全。

还有比较倒霉的一点,就是去的时候飞机晚点了2小时30分钟,回的时候晚点2个小时,好在我们早就有些心理准备了,因为最近台风影响,上海的机场一直受到雷雨天气影响。其他时候晚点的情况还是比较少的,我们出发前一周就出现了台风,而且正好是我们在青岛的这一周时间里影响到上海,唉,只能说运气不太好,好在飞机的时间比较早,还能赶上地铁回家。

Python中使用type的使用

  1. python中的type类
  2. 用type实现动态继承

python中的type类

python中type函数有两种用法,从pydoc中可以看到:

1
2
type(object) -> the object's type
type(name, bases, dict) -> a new type

第一种是返回参数的类型,常常用于在程序中判断参数类型用;第二种用法比较少见,使用来构建一种新的类型,用法跟class比较类似。

深刻理解Python中的元类(metaclass)一文中,对type给出了一种很深刻的理解。type起始也是一种python类,跟str、int、list、dict类或者我们自己定义的类等一样,这种类有两种构造方法,对应上述的两种type用法。type一个元类,或者说是类的类,也就是说它的实例是一个类,是大部分python内置类型都是type的实例。在python中class关键字构造类的时候,也是使用type来实现的。此文中还介绍到了__metaclass__关键字的用法,这个就比较高端了,以后在讨论。

用type实现动态继承

“动态继承”这个词不一定准确,是在我使用flask_sqlalchemy模块进行数据库操作时。sqlalchemy提供了ORM模型,可以使用python中的class来跟数据库中的table对应,进行相关的CRUD操作,但是此时定义的model类需要继承自一个特殊的父类,这个父类需要先创建Flask实例,再从父类中产生包含数据库连接信息的db对象,再从db对象中获取这个特殊的父类(db.Model),这个做法跟面向接口编程的思想是不相符的。我希望在我定义model类的时候并不需要先实例化flask以及指定数据连接,也就是说我可以先定义model类,包括指定字段(对应到数据库表的字段)和成员函数,然后在再创建Flask实例时,让这些类继承自db.Model,实现动态的继承。

当然,还有另一种方法就是从sqlalchemy的Base作为父类产生model类,也是一种比较好的思路的,但这里先不讨论。

使用动态类继承的话,我们的代码就可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import models
from new import classobj


def getAllTables(app):
'''
app is Flask instance.
'''

app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)

Tables = {}
for i in models.__dict__.iteritems():
if type(i[1]) is classobj:
tablename = i[0]
Tables[tablename] = type(tablename, (db.Model,), i[1].__dict__)

return (db, type("Tables", (), Tables))

models.py中定义了所有的model类,上述函数的作用是,遍历models.py中的所有类,并使用type构建一个新的类,使后者继承自db.Model。

如何在vim中添加Alt键开头的快捷键映射

  1. 前面的话
  2. vim中的快捷键映射
  3. 问题解决

前面的话

最近想好好把python学一学,计划是先学习一下flask,结合vue做一些简单的网站之类,之后再学学爬虫、图像处理、机器学习之类的东西。看了一下大家写Python好像没有什么比较推崇的IDE,又不像java那么依赖IDE做补全和重构,加上自己之前用VIM写python感觉特别流畅,所以就想用VIM自己搭一个python开发环境。

参考了一个youtube上标题貌似是“Use vim as python IDE”的视频,学着上面的指导安装了python-mode、ctrlP、jedi、powerline和rope这些vim插件,但是在装完rope使用的时候,遇到了一个问题,就是rope的代码补全帮助 (RopeCodeAssist命令) 不能用,作为rope里我认为最牛逼的一个功能没有之一,不能用的话也太让人揪心了。

整了好几个小时以后发现不是rope的问题,是vim里面快捷键的问题。我在vim的普通模式直接输:RopeCodeAssist命令是可以用的,但是通过快捷键<M-/>去没有,而是出来了搜索功能,就想是vim中普通模式下按/的效果。原因是alt开头的快捷键在xshell中映射得不对。

vim中的快捷键映射

vim的设置中,可以在.vimrc文件中使用map命令设置键位映射,如在.vimrc中增加一行map a b,那么在普通模式下输入a就会起到b的效果(在vim按b是光标向后移动一个词)。更tricky一点,用inoremap a b,那么在编辑模式下输入的a字符全都会变成b。

如果要表示一个ctrl开头的快捷键,可以用<C表示,如在map命令中,C-r表示快捷键ctrl+r,用法是先按住ctrl不放,再按r键。相应的<M和<A都是表示Alt键,<S表示shift键。

问题解决

按理说RopeCodeAssist这个命令映射到了<M-/>上,但是实际上按下alt+/以后vim并没有收到<M-/>按键值,而是收到<ESC>/。这样就很容易理解前面的现象了:在编辑模式按下<ESC>进入普通模式,在普通模式按下/进入搜索模式。

为什么会输入值不是期待的值呢?如果用过emacs会有这样的经验,b的效果是一样的,特别是在Mac这种没有meta和alt键的机器上,只能用完成原本meta键的工作。如果符合这个设定的话,那上面的行为是正确的。但是或许在mac和linux上,vim中接收到的字符会是一个特殊字符吧,与实际输入的<ESC>/不相符合。

解决的方法是在vimrc中把的值设成/,这样以后接收到<ESC>/就会触发,相当于按下了,不管是通过alt+/输入的,还是单独按和/输入的。设置的方法如下。

1
2
3
" ^[不是单独的两个字符,而是一个字符,是真实的ESC键取值,在vim中可以通过先按<C-v>,然后按<ESC>输入。
set <M-/>=^[/ " 用于触发RopeCodeAssist命令
set <M-?>=^[? " 用于触发RopeLuckyAssist命令

如何使用grep查找某文件夹下所有.py文件中的指定字符串

  1. grep的基本使用
  2. 使用grep命令的-R选项
  3. 使用find命令实现
  4. 比较

grep的基本使用

grep命令可以使用正则表达式来搜索文件中的特定字符串,而且需要搜索多个文件或者一类文件的时候可以模糊匹配文件名。例如使用*.py可以匹配所有.py结尾的文件。

但是grep模糊匹配文件名只能找当前目录下的文件,不能找到其子目录下的文件。例如命令grep "xxx" *.py,如果当前文件夹下有一个abc.py,子目录sub中有一个文件efg.py(相对路径是sub/efg.py)那么grep命令只会搜索abc.py中的字符串。

如果想要搜索当前文件夹及其子文件夹中的所有文件,那么有两种方法可以实现,分别为使用grep命令的-R选项使用find命令实现

使用grep命令的-R选项

grep命令中,-R选项能指定grep搜索文件夹,并使用--include选项指定模糊匹配的文件名,多个文件名可以使用多个--include来实现。例如下面命令实现了搜索当前目录下所有.py和.json文件中的数字串:

1
egrep -R --include="*.py" --include="*.json" "[[:digit:]]+" .

使用find命令实现

find命令用于查找文件,查找的结果可以使用-exec选项传递给后续的命令,在后续命令中可以使用{}代替find的查找结果。如下命令实现与上文相同的功能:

1
2
3
4
# `-type f`为指定find返回结果类型是文件;
# `-or`链接不同的文件名匹配条件
# `-exec`选项以" \;"结尾。
find . -name "*.py" -or -name "*.json" -type f -exec egrep "[[:digit:]]+" {} \;

比较

使用grep中的-R选项似乎更直观方便一些,而且输出结果是带文件路径的,更加全面。

如何用flask访问静态文件

在apache中,将静态文件放在指定目录下(默认是/var/www/html),就能在浏览器上直接访问了。而flask框架中稍微有些区别,因为flask下只有工程目录下的static文件夹能够用作今天文件的访问,同理,在url中,也需要加上/static路径。

如何在apache2上部署文件名为中文的网页

  1. 安装软件
  2. 使用方法

安装软件

  1. 安装中文语言包:sudo apt install language-pack-zh-hans language-pack-zh-hans-base
  2. convmv: Linux下的文件名转码工具,使用sudo apt install convmv命令进行安装。

使用方法

在Ubuntu中解压中文的html文件名的zip包时,在安装中文语言包的情况下,有时能自动转换成正确中文编码字符,但是有时解压出来的文件名是乱码,可以按照下面的指令解决乱码问题。

1
2
3
4
# 加上-O表示为指定系统的编码方式,可以使用locale命令查看系统编码方式。
unzip -O UTF-8 xxx.zip
# 将windows下默认的GBK编码文件名转换成Linux下的UTF-8编码文件名。
sudo convmv -f GBK -t UTF-8 --notest -r xxx/*

上面指令中的xxx 是你自己的zip文件名和解压以后的文件夹名称。

Mysql create new account in Ubuntu14.04

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ sudo /etc/init.d/mysql stop
$ sudo mysqld_safe --skip-grant-tables &
$ mysql -uroot -p

mysql> use mysql
mysql> insert into user(host,user,password) values('%','username',password('12345678'));

$ mysqladmin shutdown
$ sudo /etc/init.d/mysql start
$ mysql -uroot -p

mysql> grant all privileges on userdb.* to username@localhost;
mysql> flush privileges;

$ sudo /etc/init.d/mysql restart