小子 发布的文章

python多线程读取文件

网上只有多进程,有木有?理解和书写代码花了一天的时间,有木有?

多线程分块读取

# -*- coding: utf-8 -*-
import os,time
import threading

rlock = threading.RLock()
curPosition = 0

class Reader(threading.Thread):
    def __init__(self, res):
        self.res = res
        super(Reader, self).__init__()
    def run(self):
        global curPosition
        fstream = open(self.res.fileName, 'r')
        while True:
            #锁定共享资源
            rlock.acquire()
            startPosition = curPosition
            curPosition = endPosition = (startPosition + self.res.blockSize) if (startPosition + self.res.blockSize) < self.res.fileSize else self.res.fileSize
            #释放共享资源
            rlock.release()
            if startPosition == self.res.fileSize:
                break
            elif startPosition != 0:
                fstream.seek(startPosition)
                fstream.readline()
            pos = fstream.tell()
            while pos < endPosition:
                line = fstream.readline()
                #处理line
                #print(line.strip())
                pos = fstream.tell()
        fstream.close()

class Resource(object):
    def __init__(self, fileName):
        self.fileName = fileName
        #分块大小
        self.blockSize = 100000000
        self.getFileSize()
    #计算文件大小
    def getFileSize(self):
        fstream = open(self.fileName, 'r')
        fstream.seek(0, os.SEEK_END)
        self.fileSize = fstream.tell()
        fstream.close()

if __name__ == '__main__':
    starttime = time.clock()
    #线程数
    threadNum = 4
    #文件
    fileName = 'IPData.txt';
    res = Resource(fileName)
    threads = []
    #初始化线程
    for i in range(threadNum):
        rdr = Reader(res)
        threads.append(rdr)
    #开始线程
    for i in range(threadNum):
        threads[i].start()
    #结束线程
    for i in range(threadNum):
        threads[i].join()

    print(time.clock() - starttime)

多线程按行读取

#在上面的代码中使用open(file, 'r')产生的句柄每次在线程锁里面pop()就好了。

python之排序算法

快速排序

取一个元素,剩余元素与这个元素比较,小的放左边,大的放右边,依此循环嵌套,以下是实现的代码:

lis = [18,2,4,54,64,56,77]
def quicksort(lis):
	return [] if lis == [] else quicksort([x for x in lis[1:] if x < lis[0]]) + [lis[0]] + quicksort([x for x in lis[1:] if x >= lis[0]])
print(quicksort(lis))

Oracle sql杂记

一些注意点

-- || 连接字符串和字段
-- 所有数据区分大小写
-- IN 语句的范围内存在NULL对结果无影响
-- NOT IN 语句中范围内存在NULL,则不返回任何数据
-- NULL计算后的值还是NULL
-- 日期 - 数字 = 日期
-- 日期 - 日期 = 数字

一些函数

DECODE(a, 1, '男', 2, '女') -- 你懂的
NVL(a, 0) -- 字段为NULL的值
MONTHS_BETWEEN(a, b) -- a,b两个日期之间相差的月数
ADD_MONTHS(sysdate, 2) -- 在日期上加上指定的月数
NEXT_DAY(sysdate, '星期一') -- 下一个星期一
LAST_DAY(sysdate) -- 一个月的最后一天
WITH sql1 as (SELECT * FROM test) SELECT * FROM sql1 WHERE  -- with语句

select lpad('tech', 2) from dual -- te
select lpad('tech', 8, '0') from dual -- 0000tech

TRUNC(TO_DATE('24-Nov-1999 08:00 pm', 'dd-mon-yyyy hh:mi am')) -- '24-Nov-1999 12:00:00 am' 
TRUNC(TO_DATE('24-Nov-1999 08:37 pm', 'dd-mon-yyyy hh:mi am','hh')) -- '24-Nov-1999 08:00:00 am'

TRUNC(89.985, 2) -- 89.98
TRUNC(89.985) -- 89
TRUNC(89.985, -1) -- 80

select t.Name, case t.id when 1 then 'zhao' when 2 then 'qian' when 3 then 'sun' else 'li' end "fname" from T t

WMSYS.WM_CONCAT -- 行转列

一些常见的报错

未明确定义列

这一般只有在有子查询的sql语句中才会出现的错误,以为子查询的结果中有同名的列。如:

select to_char(dateline, 'yyyy-mm-dd') as dateline from test_table

这样的sql语句作为子句的时候,ORACLE会认为有两个同名的dateline列。解决办法就是将as后面的dateline改为其他的,如:fdateline

php杂记

逻辑运算

对于整个表达式来说:

或(|| or)两个同时为真则为真
与(&& and)有一个为真则为真
#这里可以用三目运算实现,这里只是为了说明逻辑关系。
$data = array(
    array('a'=>'a','b'=>''),
    array('a'=>'','b'=>'b'),
    array('a'=>'a','b'=>'b')
);
while(list(,$item) = each($data)) {
    ($item['a'] and $item['b']) and ($result = $item['a'] . $item['b']) or ($item['a'] and ($result = $item['a'])) or ($item['b'] and ($result = $item['b']));
    var_dump($result);
}
// string(1) "a"
// string(1) "b"
// string(2) "ab"

位运算

位的偏移运算,2进制

//   1
// 100 化成十进制 2的平方 = 4
echo 1<<2;

类型自动转换

可悲啊,在公司的群里面,发了下面的一道,居然没有一个人去尝试执行结果。

var_dump(0 == 'string'); // true
var_dump(true == 'string'); // true
var_dump(0 == false); //true

都是true?相信后两个的执行结果都能理解,为什么第一个也是true呢?
intval('string'); //0 看到木有,当字符串跟数字比较的时候,php会自动转换字符串为数字,啊哈。再来看看这个 intval('2string'); //2

创建多级目录

mkdir('/test1/test2', 0777, true); //最后一个参数设为true就可以了

正则杂记

验证手机号码

中国移动号段 1340-1348 135 136 137 138 139 150 151 152 157 158 159 187 188 147
中国联通号段 130 131 132 155 156 185 186 145
中国电信号段 133 1349 153 180 189
其他 181 182 183 184
^(13[0-9]|15[0-9]|14[0-9]|18[0-9])\d{8}$
^(1[3-5][0-9]|18[0-9])\d{8}$
^(1[3-58])\d{9}$

验证邮箱

^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,4}$

验证日期

^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$

验证时间

格式:时:分:秒

^([01]?\d|2[0-3]):[0-5]?\d:[0-5]?\d$

验证url

^\b(((https?|ftp):\/\/)?[-a-z0-9]+(\.[-a-z0-9]+)*\.(?:com|edu|gov|int|mil|net|org|biz|info|name|museum|coop|aero|[a-z][a-z]|((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d))\b(\/[-a-z0-9_:\@&?=+,.!\/~%\$]*)?)$

环视

以前一直没明白正则的环视的使用环境,网上的那些例子不用环视也能写出来,而且更容易理解。其实,在需要匹配的字符串有长度限制的时候,而且有其他的特殊要求的时候,用环视能很好的解决问题。这样说,还太抽象了,下面看例子:

#有待更新

一些注册表单会用到的正则

用户名(允许字母、数字、下划线、减号、中文)

^[A-Za-z0-9_\-\u4e00-\u9fa5]+$
^[A-Za-z0-9_\-\x{4e00}-\x{9fa5}]+$

真实姓名(允许字母、中文)

^[A-Za-z\u4e00-\u9fa5]+$    // js
^[A-Za-z\x{4e00}-\x{9fa5}]+$    // php

http及https的url

^http[s]?:\/\/([\w-]+\.)+[\w-]+([\w-./?%&=]*)?$

IP v4,下面把四个展开写是为了看起来比较直观,其实可以写的更短一点。

^(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)$

验证子网掩码

^(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$

flush这个函数

这个函数呢,在每个浏览器下的作用结果是不一样的:

  • IE下,接受到256个字节之后才开始显示
  • Chrome下,接受到2048个字节之后才开始显示

$my_string_var = 'test...';
echo '';
for($i = 1, $i <7, $i++) {
	echo str_pad($my_string_var, 2048, ' ');
	@ob_flush();
	flush();
	sleep(1);
}

file_get_contents这个函数

当要获取的URL资源不存在的时候,这个函数在linux和windows下返回的结果是不一样的。

在windows下,当访问的页面返回404的时候,file_get_contents不会去获取response的body的值,会返回false

而在linux下他会去获取404的HTML页面的内容。

上述情况和网络环境有关。

所以去判断一个远程文件是否存在的时候,不能使用file_get_contents($url,0,null,0,1),而应当去获取response的头状态。

css杂记

css margin重叠的问题

是不是经常有的时候子标签的margin变成了父标签的margin了,嗯哼,试试下面的。

/*任选一个*/
overflow:hidden;
zoom:1;
border-top: 1px solid #ccc;

css baseline

是不是a标签下的img标签下方都是有嗲空隙的?那是因为img标签是内联元素,默认是按照baseline对齐的,犹如那英文四线格中的第三根线。解决办法:

  1. 设置成块级元素
  2. 设置垂直对齐方式

clearfix

/*清除浮动的良药啊*/
.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}
.clearfix{*zoom:1;}

IE6,7下z-index失效

...

lxml 加 beautifulsoup with 多线程(Snail)

抓取的时候,去获取网页中指定的内容,最基本的办法就是使用正则获取,但要是要处理的网站多了,写正则岂不写死。于是哥就写了个类,看代码:

蜗牛号基类

# -*- coding: utf-8 -*-
import threading, Queue
import urllib2, cookielib
from lxml.html.soupparser import fromstring

class Snail(threading.Thread):
	def __init__(self , *argv):
		self.buildBrowser(*argv)
		super(Snail, self).__init__()
	def buildBrowser(self, *argv):
		self.cookie = cookielib.CookieJar()
		opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie))
		opener.addheaders = []
		opener.addheaders.append(('User-Agent', 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.904.0 Safari/535.7'))
		opener.addheaders.append(('Accept', '*/*'))
		opener.addheaders = opener.addheaders + [t for t in argv]
		urllib2.install_opener(opener)
	def parse(self, link, data = None):
		content = self.handle(link, data).read()
		tree = fromstring(content)
		return tree
	def handle(self, link, data = None):
		return urllib2.urlopen(urllib2.Request(link, data))
	def save(self):
		pass
snail = Snail(('Cookie','这边可以自己填写'))

需要lxml模块支持,可以到 http://lxml.de/ 下载,centos下的安装方法:

yum -y install libxml2-dev libxslt-devel
cd /usr/local/src
wget http://lxml.de/files/lxml-2.3.2.tgz
tar vzxf lxml-2.3.2.tgz
cd lxml-2.3.2
python setup.py install

cd ../
wget http://www.crummy.com/software/BeautifulSoup/download/3.x/BeautifulSoup-3.2.0.tar.gz
tar vzxf BeautifulSoup-3.2.0.tar.gz
cd BeautifulSoup-3.2.0
python setup.py install

基类的使用实例

线程锁rlock

# -*- coding: utf-8 -*-
from Snail import Snail
import threading

rlock = threading.RLock()
class Mphone(Snail):
	def __init__(self):
		super(Snail, self).__init__()
	def process(self, numhead):
		#做点实际处理的事情
		pass
	def run(self):
		while True:
			rlock.acquire()
			#线程锁锁定资源的时候,取值
			rlock.release()
			#可以在某个特定条件下 break 掉循环
			self.process(numhead)
if __name__ == '__main__':
	threadnum = 4
	threads = []
	for i in range(threadnum):
		mphone = Mphone()
		threads.append(mphone)
	for i in range(threadnum):
		threads[i].start()
	for i in range(threadnum):
		threads[i].join()

可能会遇到的一些问题

TypeError: cannot concatenate 'str' and 'NoneType' objects
#解决办法
unicode('这边是要解析的字符串', 'utf-8', errors='ignore')

php调用python服务

侃侃:公司用的php的popen以命令的形式调用python,首先说说这样做的缺点。

php执行命令行调用python的缺点

popen('python test.py [参数]', 'r');
  1. 缺点一:windows默认的是gbk编码,当php中传utf-8中文参数的时候,python接收到的参数会有问题。

    #当然,这是有解决的办法的,就是windows下转换一下字符的编码,linux不用转换。再来python接收参数的时候肯定也要转换编码了,烦不烦?
  2. cmd命令或者shell命令是有长度限制的,传的参数过长的时候,接收到的参数就不会完整。

  3. 执行shell命令是有危险的,万一参数里面多了个啥,你知道的。

    #这也能解决,php中的函数escapeshellarg,嗯哼先给他escape一下。
    

那怎么办呢?

python socket server

不多说,不清楚的百度"socket",下面上代码(写的一个php调用python服务美化javascript的应用,服务器端python):

#代码中引用的模块将会在附件中给出
import sys, json
import traceback
import SocketServer
from daemon import Daemon
import jsbeautifier

class Todo:
    def __init__(self):
        print('Welcome!')
    def test(self, args):
        res = jsbeautifier.beautify(args[0].encode('utf-8'))
        return res;
    def error(self, args):
        return 'not function!'

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                data = self.request.recv(1024)
                if not data:
                    print('end')
                    break
                data = json.loads(data)
                res =  getattr(self._object, data['func'], 'error')(data['args'])
                if not res:
                    res = ''
                res = str(len(res)).rjust(8, '0') + str(res)
                self.request.send(res)
            except:
                print('error in ThreadedTCPRequestHandler :%s, res:%s' % (traceback.format_exc(), data))

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

class Server(Daemon):        
    def conf(self, host, port, obj):
        self.host = host
        self.port = port
        self.obj = obj
        ThreadedTCPServer.allow_reuse_address = True
    def run(self):
        ThreadedTCPRequestHandler._object = self.obj
        server = ThreadedTCPServer((self.host, self.port), ThreadedTCPRequestHandler)
        server.serve_forever()

if __name__ == '__main__':
    server = Server('/tmp/daemon-tortoise.pid')
    server.conf('0.0.0.0', 1990, Todo())
    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            server.start()
        elif 'stop' == sys.argv[1]:
            server.stop()
        elif 'restart' == sys.argv[1]:
            server.restart()
        else:
            print("Unknown command")
            sys.exit(2)
        sys.exit(0)
    else:
        print("usage: %s start|stop|restart" % sys.argv[0])
        sys.exit(2)

解释一下,上面这些代码是用python创建一个socket服务器,并且加入系统的守护进程。Todo里面实现策略工厂啥的,你懂的。使用方法:

python sever.py [start|stop|restart]
#接着设为系统启动项就O了。

php通过socket调用python

//代码中引用的文件将会在附件中给出,附件中还给出了php并发的写法
require 'socketapi.php';
header("Content-type: text/html; charset=utf-8");
$s = new server('192.168.1.8', 1990);
$code = <<<EOT
/*   美化:格式化代码,使之容易阅读            */
/*   净化:去掉代码中多余的注释、换行、空格等    */
/*   压缩:将代码压缩为更小体积,便于传输        */
/*   解压:将压缩后的代码转换为人可以阅读的格式    */

/*   如果有用,请别忘了推荐给你的朋友:        */
/*   javascript在线美化、净化、压缩、解压:http://box.inote.cc/js   */

/*   以下是演示代码                */

    var getPositionLite = function(el) {        var x = 0,        y = 0;        while (el) {            x += el.offsetLeft || 0;            y += el.offsetTop || 0;            el = el.offsetParent        }        return {            x: x,            y: y        }    };
/*   更新记录:                    */
    var history = {
        'v1.0':    ['2011-01-18','javascript工具上线']
    };
EOT;
$res = $s->obj('Todo')->test($code);
echo '<pre>'.$res.'</pre>';

附件,你懂的。

client.zip | server.zip

bash杂记

带有颜色的echo

设置颜色的格式: \e[背景色;前景色;高亮m\e[0m

\e或\033
背景色:0 透明(使用终端颜色), 40 黑, 41 红, 42 绿, 43 黄, 44 蓝 45 紫, 46 青绿, 47白(灰)
前景色:30 黑 31 红, 32 绿, 33 黄, 34 蓝, 35 紫, 36 青绿, 37 白(灰)
高亮:高亮是1,不高亮是0。(m后面紧跟字符串)

#红色的helloworld
echo -e '\033[0;31;1mhelloworld\033[0m'

screen命令

在SSH断开的情况下,服务器端继续执行程序。

screen -S test
#输入要执行的命令,enter
#Ctrl + a + d保存screen
#查看所有screen
screen -ls
#恢复screen
screen -r test
#退出screen
exit

crontab命令

crontab [-u 用户名] [-elr]
#crontab -e
#分  时  日  月  周    [用户]  command
#每分钟执行一次第一个参数可以写成样 1-59 或者 */1
# .---------------- minute (0 - 59) 
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ... 
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)  OR sun,mon,tue,wed,thu,fri,sat 
# |  |  |  |  |
# *  *  *  *  *  command to be executed

crontab中的环境变量问题

有时候crontab执行脚本获取不到想要的结果,而直接在ssh里执行的时候是正常的,就是环境变量的问题,在要执行的脚本中加入下面两行。

. /etc/profile
. ~/.bash_profile

计算程序运行时间

time ./test

linux文件压缩解压

.tar
解包: tar xvf FileName.tar
打包:tar cvf FileName.tar DirName
(注:tar是打包,不是压缩!)
---------------------------------------------
.gz
解压1:gunzip FileName.gz
解压2:gzip -d FileName.gz
压缩:gzip FileName
.tar.gz
解压:tar zxvf FileName.tar.gz
压缩:tar zcvf FileName.tar.gz DirName
---------------------------------------------
.bz2
解压1:bzip2 -d FileName.bz2
解压2:bunzip2 FileName.bz2
压缩: bzip2 -z FileName
.tar.bz2
解压:tar jxvf FileName.tar.bz2
压缩:tar jcvf FileName.tar.bz2 DirName
---------------------------------------------
.bz
解压1:bzip2 -d FileName.bz
解压2:bunzip2 FileName.bz
.tar.bz
解压:tar jxvf FileName.tar.bz
---------------------------------------------
.Z
解压:uncompress FileName.Z
压缩:compress FileName
.tar.Z
解压:tar Zxvf FileName.tar.Z
压缩:tar Zcvf FileName.tar.Z DirName
---------------------------------------------
.tgz
解压:tar zxvf FileName.tgz
.tar.tgz
解压:tar zxvf FileName.tar.tgz
压缩:tar zcvf FileName.tar.tgz FileName
---------------------------------------------
.zip
解压:unzip FileName.zip
压缩:zip FileName.zip DirName

设置开机启动

vi /etc/rc.d/rc.local

SCP命令

scp -r root@type.so:/var/www/html/ -P 22 /var/www/html/

rpm

# 导出文件
rpm2cpio file.rpm | cpio -div
# 查看rpm包列表内容
rpm -qpl file.rpm

修改时区

cp /usr/share/zoneinfo/Shanghai /etc/localtime
hwclock -w
# crontab重启必须的,不然设定的动作将会按照老的时间来
service crond restart

python杂记

python实现switch语句

{
    '0' : labmda : print('你是男的还是女的'),
    '1' : labmda : print('你是男的'),
    '2' : labmda : print('你是女的'),
}.get('1')()

python实现三目运算

#example1
(labmda x,y: x < y and x or y)(1,3)
#example2
(labmda x,y: x if x < y else y)(2,4)

python中exec和eval的用法

#example exec
exec("mult = lambda x,y: x**y")
print(mult(2, 3))
#example eval
print(eval("lambda x,y: x**y")(2,3))

python中enumerate带索引的遍历

str = 'mystring'
#lst = ['hello',',','type','.','so']
for idx , ele in enumerate(str):
    print(idx,ele)

python中for else语句

import math
for i in range(100):
    for t in range(2, int(math.sqrt(i)) + 1):
        if i % t == 0:
            break
    else:
        print(i)

python动态导入模块

mymod=__import__('mypackage', fromlist=["*"])
mymod.mydef()

python按行读取文件

#sample 基本的方法
file = open("sample.txt")
while True:
    line = file.readline()
    if not line:
        break
    pass
#sample 更快的方法
file = open("sample.txt")
while True:
    lines = file.readlines(100000)
    if not lines:
        break
    for line in lines:
        pass

python html中编码的汉字

抓取网页的时候可能会遇到(小子)这样的格式输出的汉字,我们想办法将他还原为真正的汉字

#10进制的
print(unichr(int('23567', 10)))
print(unichr(int('23376', 10)))
#16进制的
print(unichr(int('0x5c0f', 16)))
print(unichr(int('5b50', 16)))
#用HTMLParser模块
import HTMLParser
html_parser = HTMLParser.HTMLParser()
s = html_parser.unescape('小子')
print(s)

获取本机IP

import socket
print(socket.getaddrinfo(socket.gethostname(),None)[-1][4][0])

python中list相减

python中两个list可以相加,却不能相减,是不是很纠结。

list1 = [1, 2, 3, 4, 5]
list2 = [1, 3, 5]
#example1 转换为集合相减
list3 = list(set(list1) - set(list2))
#example2
list3 = [i for i in list1 if i not in list2]

判断list1是否为list2的子集

list1 = [1,3,5]
list2 = [1,3,5,7]
if all(x in list2 for x in list1):
    print('子集')

读取大文件的指定行

def getline(thefilepath, desired_line_number): 
    if desired_line_number < 1: return ''
    for current_line_number, line in enumerate(open(thefilepath, 'rU')): 
        if current_line_number == desired_line_number-1: return line
    return ''

print写文件

f = open('out.txt','w+')
print >> f, 'hello', 'world'
f.close()

元祖传递函数参数

def add(a, b):
    print a + b
opnds = (1,2)
add(*opnds)

单词首字母大写

string.capwords

我愿化身石桥

shiqiao.jpg

我愿化身石桥,受五百年风吹,五百年日晒,五百年雨打,但求那少女从桥上走过……