妮神教的,没看过标准的我只能猜测,不过开始猜测的还正确了
我在一个包文件里这么定义了一个常量
(defconstant +levels+ (vector :error :warning :info :debug))
load的时候说重复定义,这显然是不正确的,我其他地方都没定义过,显然后边那个值又计算了。我在群里问就是后边这个值是不是又计算了一次。
不过我不知道原因是load了多次导致的
妮神的讲解就是,加载到repl的时候会load多次,然后 就会定义多次,而常量不允许定义多次,cl的实现就会判断定义的时候后边的值是否eql,eql就通过,不eql就报错。而vector虽然是不变长的,但是还不是一个对象,执行两次不eql,所以会报错。
直接用defparameter定义的,包里边自己别修改一般不会有问题吧。
Read more...
common lisp包编译方法
在妮神帮助下,学习了很多cl的知识,后边都总结一下。
本想晚上洗袜子,跑步。写代码写的上火,写了一晚上写了40行cl代码,四个宏,并且功能还没做完。想给框架先写个log模块的,用宏可以编译前判断log打印等级决定生成是否打印,现在整的完全不想写cl代码了[泪流满面] 洗洗睡,袜子明天起的早再洗
今天早上思路清晰多了,代码精简到34行.修复了一个bug。问题是修复了这个bug,展开式变成4行,没修复之前展开式只有一行,不爽 ,,四行的话和写个函数没啥区别了
昨晚上和今天早晨的微博,然后就不记录前后原因了。
说说怎么编译包。
首先要load 依赖包,不然会编译的时候找不到。
(ql:quickload "cl-async")
编译包的顺序,要先编译package.lisp并且load。不然编译别的文件会找不到你自己定义的包.
(load (compile-file "package.lisp"))
之后按顺序编译其他文件
(load (compile-file "logging.lisp"))
(load (compile-file "server.lisp"))
这样其实就可以执行代码了。不过退出repl从新加载的时候,顺序一样,要先load依赖包,然后loadpackage,最后load相关包文件。然后写代码测试。
Read more...
common lisp使用asdf打包程序总结
今天本来想写点web框架代码,早早睡觉的,框架代码写了一点。发现测试时候load 然后执行,想文件多了没法搞了。先看看cl打包吧。
然后就查看过的书,找讲包的内容,发现很少。就一个defpackage,实用cl编程里边讲的多一点,注意事项很多,然并卵,写完发现一样不好用。
去群里求救,需要asdf这么个东西,起了个蛋疼名。之前用过但是不知道干嘛的,文档
https://www.common-lisp.net/project/asdf/asdf.html
首页有个有意思的地方Examples
Download any of the many packages available through Quicklisp to see as many examples.
哈哈,不过文档里有。
看文档sbcl里边好像自带asdf,我装过quicklisp,并且启动repl的时候自动加载。可以直接使用(asdf:asdf-version)看到asdf的版本3.0.2
duang.asd
Read more...
(in-package :asdf-user) (asdf:defsystem duang :description "A simple Web Framework." :author "0x55aa主要定义包的依赖关系 package.lisp" :license "BSD" :version "0.0.1" :depends-on (#:cl-async) :components ((:file "package") (:file "server")))
(defpackage :duang (:use :common-lisp :cl-async) (:nicknames dg) (:export #:start-server))server.lisp
(in-package :duang) (defun start-server () ())然后代码的位置要能被sbcl发现,看文档可以自定义,等会儿看看quicklisp文档有没有。我直接放到~/quicklisp/local-projects/文件夹下了。 最后在repl里(asdf:load-system "duang") (dg:start-server)就行了 (require :duang) (load ) (ql:quickload "duang") 都行 这么点东西搞了一晚上
如何调用mac的通知中心(Notification Centers)做消息提醒
说说研究这个的起因:
妹子这几天心情不好,频发状态,为了随时了解她的动态,觉得写个接口时刻关注她是否发送新状态。mac下的通知中心是最好的消息提醒了,比ubuntu下的好多了,非常容易看到而且不烦人,所以想看看能不能调这个通知中心的接口。
系统编程肯定是可以了,但是我想用python写脚本,于是google一下,没有。改成英文找到了。。
几个关键的知识点:
osascript
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/osascript.1.html
https://developer.apple.com/library/mac/documentation/AppleScript/Conceptual/AppleScriptX/AppleScriptX.html#//apple_ref/doc/uid/10000156-BCICHGIE
这应该是osx的系统级脚本语言,类似之前windows的vbscript吧。最早就用VBscript就能写界面程序,只要一个vbs脚本,学那个的时候才刚研究编程。
无需写个脚本,osascript有个-e参数,后面可以跟一个多行的脚本语句。就这个了。
想弹出一个提示,只要终端执行:osascript -e 'display notification "Content ! !" with title "Title"'
subtitle
display notification "message" with title "title" subtitle "subtitle"
sound声音
display notification "message" sound name "Sound Name"声音文件都在
~/Library/Sounds
/System/Library/Sounds
ok,直接python调一下语句就行了。后边两个是看stackoverflow上总结的,只管记录一下,以后说不定用到,应该问的也能查到。
通知中心的偏好设置里边,appscript编辑器必须在-在通知中心里边,这样才会有提示。
https://developer.apple.com/library/mac/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html#//apple_ref/doc/uid/TP40000983-CH216-SW224
Read more...
asp.net毕业设计
额 前段时间和同学接毕业生的毕业设计,有一个中科大的就想用c#做,没办法就只能用c#了,然后装的win虚拟机,下载的vs2013免费版,期间试用时间过了,注册个账户登录就好了。大学的时候开过课,还做过大作业,基本都忘干净了。从官网看的文档,直接用的mvc5 ,ide的好处就是可以智能提示。
然后我也不懂继承关系,看教程,把继承的类给写错了,爆了一个看不懂的错误,根本找不到原因。没法,找个了asp.net的群,问了一下,大部分人都没用过mvc模式,不过其中有个人说你看一下你的model,然后我就把我的代码和官网教程对比,发现继承类写错了。。第一个问题算过去了
总之都是不了解的原因,我也想过找本书看一遍,但是就想做完毕业设计也不再碰了,就想看看官方文档做出来就行了。之后又碰到链接数据库model都对应一个数据库链接操作不会写,查了点资料,加了一个类文件,搞定了。后来还碰到外键定义的方法不会,搜索外键还不是这么叫的应该,文档上有但是看的时候过掉了,看目录有些词根本不知道是讲这个的,英文也不行。最后找到文档写出来了。
总的来说使用mvc方式开发这样的任务还是很方便很快,大多数问题都是我不了解造成的。
Read more...
DHT爬虫站-芭蕉细雨
资源多一点了,现在不到150万。种子搜索的速度不是太快,这一版和我之前用python写的不一样,之前用python写的再没做优化,内存占用还是高,不过速度快一点。
芭蕉细雨
使用sphinx做分词搜索种子信息,数据库使用postgresql,使用了redis。开始的时候使用postgresql自带的搜索进行搜索,速度已经非常好了,不过还是慢,换成专业搞搜索的就快了好多。
开始 长的要一两秒,到后来资源多了,需要十秒,我就从逻辑上进行优化,从开始就没有使用offset,我用id进行查询的分割,这种对于资源多的种子检索很好用,但是对于资源少的还是没办法。
换成sphinx,postgresql不需要单独使用一个表存储搜索字段,硬盘占用会少一点。python程序也不需要分词包,一下子占用内存少了很多。sphinx资源占用也少,并且速度就需要几十毫秒。
Read more...
记几个freebsd命令
Freebsd下查看进程打开了那些文件
procstat -f PID
FreeBSD 下的rc.conf 不重启立即生效
# sh /etc/rc
vmstat结果内容的解释
最好使用vmstat t [n]命令,例如 vmstat 5 5,表示在T(5)秒时间内进行N(5)次采样。如果只使用vmstat,无法反映真正的系统情况。
procs:
r–>在运行的进程数
b–>在等待io的进程数(等待i/o,paging等等)
w–>可以进入运行队列但被替换的进程
memoy(以k为单位,包括虚拟内核和真实内存,正在运行或最近20秒在运行的进程所用的虚拟内存将被视为active)
avm–>活动的虚拟内存
free–>空闲的内存
pages(统计错误页和活动页,每5秒平均一下,以秒为单位给出数值)
flt–>错误页总数
re–>回收的页面
pi–>进入页面数
po–>出页面数
fr–>空余的页面数
sr–>每秒通过时钟算法扫描的页面
disk 显示每秒的磁盘操作(磁盘名字的前两个字母加数字,默认只显示两个磁盘,如果有多的,可以加-n来增加数字或在命令行下把磁盘名都填上。)
fault 显示每秒的中断数
in–>设备中断
sy–>系统中断
cy–>cpu交换
cpu 表示cpu的使用状态
cs–>用户进程使用的时间
sy–>系统进程使用的时间
id–>cpu空闲的时间
解释:
如果 r经常大于 4 ,且id经常少于40,表示cpu的负荷很重。
如果pi,po 长期不等于0,表示内存不足。
如果disk 经常不等于0, 且在 b中的队列 大于3, 表示 io性能不好。
Read more...
sphinx/coreseek配置postgresql增量索引
新创建一个表保存最大id,区分主索引和增量索引
# 搜索索引相关
CREATE TABLE index_delta (
id SERIAL PRIMARY KEY,
max_id integer
);
INSERT INTO index_delta (id, max_id) VALUES (1, 0);
我这里直接插入数据,后边配置的时候直接使用update就行了,不然太麻烦。
配置文件;先大体测试了一下,应该没什么问题了,安装的3.2版本的coreseek,好多功能没有,不过够用了,先布置到线上看看效果
Read more...
source main { type = pgsql sql_host = localhost sql_user = pgsql sql_pass = sql_db = bt sql_port = 5432 # optional, default is 3306 sql_query_pre = SET NAMES 'UTF8' sql_query_pre = UPDATE index_delta set id=1, max_id=max FROM (SELECT MAX(id) AS max FROM hash) AS foo; sql_query_range = SELECT MIN(id),MAX(id) FROM hash sql_range_step = 1000 sql_query = SELECT id, hash, extract('epoch' FROM insert_time)::int AS date_added, name, files \ FROM hash WHERE id>=$start AND id<=$end AND id<=(select max_id from index_delta ) # sql_attr_uint = hash sql_attr_timestamp = date_added # sql_field_string = name # sql_field_string = files sql_query_info_pre = SET NAMES utf8 sql_query_info = SELECT * FROM hash WHERE id=$id } source delta : main { sql_query_pre = SET NAMES 'UTF8' sql_query_range = SELECT a.min_id, b.max_id FROM (SELECT MAX(id) AS max_id FROM hash) AS b, \ (SELECT max_id AS min_id FROM index_delta) AS a sql_range_step = 1000 sql_query = SELECT id, hash, extract('epoch' FROM insert_time)::int AS date_added, name, files \ FROM hash WHERE id>(select max_id from index_delta ) AND id>=$start AND id<=$end } index main { source = main path = /usr/local/coreseek/var/data/main docinfo = extern # charset_type = sbcs # rt_field = name # rt_field = files mlock = 0 morphology = none min_word_len = 1 html_strip = 0 charset_dictpath = /usr/local/mmseg3/etc/ charset_type = zh_cn.utf-8 ngram_len=0 } index delta : main { source = delta path = /usr/local/coreseek/var/data/delta docinfo = extern mlock = 0 morphology = none min_word_len = 1 html_strip = 0 charset_dictpath = /usr/local/mmseg3/etc/ charset_type = zh_cn.utf-8 ngram_len=0 } indexer { mem_limit = 64M } index main { source = main path = /usr/local/coreseek/var/data/main docinfo = extern # charset_type = sbcs # rt_field = name # rt_field = files mlock = 0 morphology = none min_word_len = 1 html_strip = 0 charset_dictpath = /usr/local/mmseg3/etc/ charset_type = zh_cn.utf-8 ngram_len=0 } index delta : main { source = delta path = /usr/local/coreseek/var/data/delta docinfo = extern mlock = 0 morphology = none min_word_len = 1 html_strip = 0 charset_dictpath = /usr/local/mmseg3/etc/ charset_type = zh_cn.utf-8 ngram_len=0 } indexer { mem_limit = 64M }sphinx自带python的api接口,在源代码的api目录里,python api/test.py MP4,可以搜索MP4的关键字,测试一下可以用。 看了一眼sphinx.py,就是请求的listen端口。这个后边慢慢研究一下。 >>> import sphinxapi >>> c = sphinxapi.SphinxClient() >>> q = c.Query('world')
freebsd上安装sphinx coreseek postgresql
基本都是coreseek官网提供的命令安装,但是在freebsd上出现很多问题,都是查找解决的。
sh buildconf.sh最后没有生成configure脚本,且提示automake: warnings are treated as errors
在 csft-4.1/buildconf.sh 文件中,查找
&& aclocal \
后加上
&& automake --add-missing \
在 csft-4.1/configure.ac 文件中,查找:
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
改为:
AM_INIT_AUTOMAKE([-Wall foreign])
这里支持pgsql接口
./configure --prefix=/usr/local/coreseek --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg3/lib/ --without-mysql --with-pgsql --enable-id64
编译的时候出错
sphinxexpr.cpp:1746:43: error: ‘ExprEval’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
可以直接修改src/sphinxexpr.cpp文件的1746, 1777和1823行,将三行中的ExprEval改为this->ExprEval
undefined reference to `libiconv'
这个直接采用官方的第三种方法了,为了方便。。
配置完建立索引的时候
source 'src1': unknown type 'pgsql'; skipping.
卧槽 4.1编译完以后一直内存段错误 ,找不到问题。换成稳定版本,libiconv采用第二种方法,成功。
/usr/local/coreseek/bin/searchd -c /usr/local/etc/sphinx.conf启动
加-h查看参数
/usr/local/coreseek/bin/search -c /usr/local/etc/sphinx.conf -a mp4 搜索
明天详细研究一下配置文件
###########
测试完真正安装的时候又报错了。
编译mmseg的时候报错ThesaurusDict.h:12:17: error: expected namespace name
编辑文件:ThesaurusDict.h
在头部找到:#include
再其下加入一行代码:#include
3.2修改src/sphinxexpr.cpp的1080,1013,1047行
Read more...
tornado Future相关理解
昨天下午写了一个postgresql访问接口库psycopg2的异步封装,这个库是支持异步请求postgresql的,所以只是简单的封装了一下。简介了torndb和一个网上写好的异步库momoko,又找到一个网上分享的ppt。写的时候直接用gen.coroutine装饰接口函数,这样我再models里写的时候直接yield query()就行了。
写完对tornado异步封装的代码也看了一些,有了一些理解,不过没有循序看。之前看到时候感觉太乱实在不想从新看了。先记录一下,可能很多错误。
future是保存的异步的结果,这个类是在concurrent.py文件里。
result()方法是返回结果,通过done()方法判断执行结束,就可以用result方法获得结果。
set_result()是设置结果,像gen.Task()就是调用一个带有callback参数的异步方法,返回future,变成为一个可以使用yield协程 的函数,对他就是个函数。2333 这个函数里边就使用了set_result()方法,Task这个函数其实不复杂写了那么多的目的就是把Task装饰的那个函数里边callback的参数用set_result()设置成返回值,保存在future里。哈哈 我觉得以后我看这里也不会看懂,还不如直接看代码容易。这里用到了带名字的元组,这个看到过没用过。set_result()用的地方很多
其他的基本就是异常处理,
先看看其他周边,想gen.Return是继承自Exception所以这个用raise,这个异常会在后边用的时候捕获到,然后当做结果。
其他的没看,代码没看全,没看到那些类和函数。
coroutine这个装饰器,内容很多。
先是执行函数,有返回值,保存,然后如果抛出Return exception 获取里边的值,或者其他程序异常。
没有异常,就判断结果是否是生成器,不是生成器直接将结果set_result保存到future并返回结果,如果是next执行之,如果执行完或者Return设置执行完的值,这里异常处理和上边一样,执行完后如果没有异常产生,执行Runner(),handler_yield没看,主要看了run(),处理方式基本相同,主要就是将刚刚执行的结果通过send方法返回给yield前边的变量,就是类似a = yield query()这种,将结果返回给a。
然后总结一下思路,可能不太对。requesthandler执行的时候,执行相对应的http method,如果返回的不是future,那ok,流程上边写过了,执行完没有异常并判断不是个生成器类型就会直接在future保存结果并返回。为什么还要保存到future中呢。因为requesthandler里的execute也是经过coroutine修饰过了。
发现返回一个future,因为比如一个get方法被我们用coroutine装饰了。然后他就yield,这个的返回结果就是你get方法的结果了。
然后执行对应的我的model里的search_result(),然后执行query语句,我都是用gen.Return返回的结果,怎么感觉这么复杂。。。感觉这样写不太对,不太符合设计
query方法先获取cursor,这些都是coroutine修饰的,都是返回的生成器类型。(之所以这样写,这个库只我自己用,我不喜欢callback的模式,感觉yield写起来也方便看起来也方便,封装的时候参数也不写callback了)使用gen.Task获取conn,为啥用这个因为这个必须设置callback,然后里边的callback参数就是conn,这样task会将装饰的函数参数callback的参数最终作为结果返回。这里说装饰也不太对,Task不是个装饰器。感觉跟functools里的partial很像,但不一样,他返回一个future。这样就会最终返回给我链接数据库的conn,在cursor我是用gen.Return返回corsors,这个会捕获到Return异常直接设置到future里当做结果,最后通过runner里的run返回给yield关键字前的cursor变量。这样就获取到了cousor。。。。。下边执行语句的时候和这个流程一样
Read more...