标签归档:python

python skimage图像处理

skimage即是Scikit-Image。基于python脚本语言开发的数字图片处理包,比如PIL,Pillow, opencv, scikit-image等。 PIL和Pillow只提供最基础的数字图像处理,功能有限;opencv实际上是一个c++库,只是提供了python接口,更新速度非常慢。scikit-image是基于scipy的一款图像处理包,它将图片作为numpy数组进行处理,与matlab一样。 阅读全文

python使用esmre代替ahocorasick实现ac自动机[多模匹配]

为什么会用AC自动机? 如果你想知道一篇文章有没有你要过滤的敏感词,怎么办? 不可能用正则一个个的匹配吧?  敏感词超过300个之后,用Trie来构建模式树 (字典树)的速度优势相当的明显… …

特别说下,trie图也是一种DFA,可以由trie树为基础构造出来,对于插入的每个模式串,其插入过程中使用的最后一个节点都作为DFA的一个终止节点。

如果要求一个母串包含哪些模式串,以用母串作为DFA的输入,在DFA 上行走,走到终止节点,就意味着匹配了相应的模式串。

ps: AC自动机是Trie的一种实现,也就是说AC自动机是构造Trie图的DFA的一种方法。还有别的构造DFA的方法…

不扯淡了,我们后端都是python写的,python的ahocorasick模块跟我们的业务不太匹配,问题是这样的 !    如果你的服务是用来做敏感词匹配,也就是说所有文章里面只要含有一个关键词,那就说明匹配了。  但是我们的业务是文章中的所有能匹配到的关键词都一一的抽取出来。   我想有些朋友可能还不太明白,那么我举个例子, 如果我的关键词里面有宝马和马,那么用python的ahocorasick库只会得到宝马,而不会得到马。  问题是处在马这个字节是在宝马的链条里面的。  如何避开这个问题,我们也懒得自己重写了,已经有人给出了解决的模块。  已经测试完成,并上线使用了。

安装简单,直接pip install esmre

import esm
index = esm.Index()
index.enter("宝马")
index.enter("马")
index.enter("奔驰")
index.enter("保时捷")
index.fix()
index.query("哎呀,今天在楼下看到了宝马,我老家倒是有养马的,以前的邻居有个奔驰,不对是保时捷,大爷的,都是马")

再来一个完整的例子.  后续有时间我会把ac自动机的服务集成到rpc服务里面,然后用docker打包。

#coding:utf-8
import esm
index = esm.Index()
with open('keyword.config','r') as f:
    for i in f.readlines():
        index.enter(i.strip())
    index.fix()
 
str = """
head&shoulders海飞丝Hershey‘s
Loreal欧莱雅LUX2
力士
L’OREALMagic2
美即
MysteryCity
谜城
NO.1BABY2
RESIN
SANXIAO
SHISEIDO FINE TOILETRY2
SKII美之匙
Tao yu tang2
淘雨堂
whoo倍加洁
卡尔林奈
娇韻诗
德国帮宝适
Perfect puff2
See Young2
落健
高夫
"""
data = index.query(str)
print data

测了几天,性能还是可以的,500KB的文章,6000多个关键词,消耗的时间在0.002左右,相比ahocorasick一点都不差的。  观察了下,esmre是没有发现内存异常泄露等问题。

[2015-06-12 23:34:01,043] INFO extractor "Get keywords takes 0.0003 seconds"
[2015-06-12 23:34:01,069] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:01,178] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:02,372] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:02,386] INFO extractor "Get keywords takes 0.0012 seconds"
[2015-06-12 23:34:02,631] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:03,656] INFO extractor "Get keywords takes 0.0021 seconds"
[2015-06-12 23:34:03,744] INFO extractor "Get keywords takes 0.0001 seconds"
[2015-06-12 23:34:03,785] INFO extractor "Get keywords takes 0.0001 seconds"
[2015-06-12 23:34:03,910] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:04,031] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:05,004] INFO extractor "Get keywords takes 0.0035 seconds"
[2015-06-12 23:34:05,579] INFO extractor "Get keywords takes 0.0055 seconds"
[2015-06-12 23:34:05,602] INFO extractor "Get keywords takes 0.0005 seconds"
[2015-06-12 23:34:05,662] INFO extractor "Get keywords takes 0.0010 seconds"
[2015-06-12 23:34:06,125] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:06,299] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:06,404] INFO extractor "Get keywords takes 0.0003 seconds"
[2015-06-12 23:34:07,396] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:07,595] INFO extractor "Get keywords takes 0.0004 seconds"
[2015-06-12 23:34:08,725] INFO extractor "Get keywords takes 0.0015 seconds"
[2015-06-12 23:34:09,504] INFO extractor "Get keywords takes 0.0004 seconds"
[2015-06-12 23:34:09,515] INFO extractor "Get keywords takes 0.0005 seconds"
[2015-06-12 23:34:10,650] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:11,206] INFO extractor "Get keywords takes 0.0003 seconds"
[2015-06-12 23:34:12,298] INFO extractor "Get keywords takes 0.0002 seconds"
[2015-06-12 23:34:12,319] INFO extractor "Get keywords takes 0.0001 seconds"
[2015-06-12 23:34:13,547] INFO extractor "Get keywords takes 0.0006 seconds"
[2015-06-12 23:34:13,853] INFO extractor "Get keywords takes 0.0005 seconds"

 

摘自: http://xiaorui.cc   http://xiaorui.cc/?p=1649

让python调用mongo读写速度加速10倍的方法

1.把mongo读写封装成api

2.在api初始化时保持数据库长链接;并且用线程每2分钟遍历一次所有的表并count一次

import sys
import time
import pymongo
import json
import log
import traceback
import threading

//库名test,表名test_table
server_list = ['test-mongos.all.serv:6365' for i in range(8)]
conn_str = "mongodb://test:123456@" + ",".join(server_list) + "/test"
print conn_str
conn = pymongo.MongoClient(conn_str)
test = conn.test

def load_cache(){
    #load cache
    try:
        table_names_cache = test.collection_names()
        for tb in table_names_cache:
            print tb, test[tb].count()
    except:
        traceback.print_exc()
        log.warn("acl data load failed")

    # threading reflash
    bg_job = threading.Timer(120, load_acl_data, ())  #120 seconds
    bg_job.start()
}

#query
start_time = time.time()
condition = {"id": "abc"}
doc_iter = test['test_table'].find(condition, {"_id": 0}).batch_size(15).limit(1)
docs = list(doc_iter.max_time_ms(200000))    #200000ms
end_time = time.time()
print "use time:" + str(end_time - start_time)

你会发现使用主键或唯一索引进行增删改查时,调这个api的平响会是你直接调原生lib读写耗时的1/10 – 1/20左右(平响20-50ms=>3-5ms),原理应该就是count请求导致了主键和唯一索引短时间内被cache,此时增删改定位数据位置时用到了内存中的索引cache所以速度变快。

(注:mongo集群需要有比较充沛的内存)

yan 20170815 01:33

python发送post请求

pythonpost

python发送post请求代码示例:


import sys
import httplib, urllib
import traceback

def post(params):
	'发送post请求'
	result = {'status':500, 'reason':'', 'response':'', 'headers':''}
	httpClient = None
	try:
	    data = urllib.urlencode(params['data'])
	    httpClient = httplib.HTTPConnection(params['hostname'], params['port'], timeout=30)
	    if params.has_key('header'):
		httpClient.request("POST", params['path'], data, params['header'])
	    else:
		httpClient.request("POST", params['path'], data)
	    response = httpClient.getresponse()
	    result['status'] = response.status
	    result['reason'] = response.reason
	    result['response'] = response.read()
	    result['headers'] = response.getheaders() #获取头信息
	except:
	    self.writelog("error", 'post fail! [' + params['path'] + '][' + data + ']\n' + self.get_trace())
	finally:
	    if httpClient:
		httpClient.close()
	return result

def get_trace():
	'获得异常栈内容'
	try:
	    errmsg = "Traceback (most recent call last):\n "
	    exc_type, exc_value, exc_tb = sys.exc_info()
	    for filename, linenum, funcname, source in traceback.extract_tb(exc_tb):
		errmsg += "  File \"%-23s\", line %s, in %s() \n\t  %s \n" % (filename, linenum, funcname, source)
	    errmsg += str(exc_type.__name__) + ": " + str(exc_value)
	    #traceback.print_exc()
	except:
	    errmsg = ''
	return errmsg


#测试post请求
params = {}
params['hostname'] = "test.yanjingang.com"
params['port'] = 80
params['path'] = "/api.php"
params['data'] = {'t': 25}
params['timeout'] = 30
params['header'] = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}

res = self.post(params)
print res['status']
print res['response']



执行结果:

python的类属性与实例属性——继承与java或php的差异

写java、php写多了,以为python的类跟他们是一样的,结果今天遇到一个类属性的诡异现象,跟完发现在类属性上,python有个很特殊的地方,就是在子类调用父类的方法修改父类属性时,会影响到同进程的其它子类实例。例子如下:

class TestBase:
 test={}
def __init__(self, key):
self.test[key] = 1
def get(self):
return self.test

class TestA(TestBase):
def get(self):
return self.test

class TestB(TestBase):
def get(self):
return self.test

key = ‘aaa’
tb = TestA(key)
print tb.get()

key = ‘bbb’
tb = TestB(key)
print tb.get()

我想当然的认为输出结果会是:

{‘aaa’: 1}
{‘bbb’: 1}

没想到实际输出的是:
{‘aaa’: 1}
{‘aaa’: 1, ‘bbb’: 1}

也就是说,两个不同的子类的不同实例之间,类的属性竟然是打通的。。。查了一下后发现python的逻辑是这样的:在定义类属性的位置声明的属性是类属性改变它的值会影响所有继承它的类实例;如果不声明直接在函数中使用self.xxx的属性,是实例属性,生命周期只存在于当前实例中,对当前实例外没有任何影响。

也就是上边的badcase解决方法是:

class TestBase:
def __init__(self, key):
self.test={}
self.test[key] = 1
def get(self):
return self.test

class TestA(TestBase):
def get(self):
return self.test

class TestB(TestBase):
def get(self):
return self.test

key = ‘aaa’
tb = TestA(key)
print tb.get()

key = ‘bbb’
tb = TestB(key)
print tb.get()

 

输出结果:

{‘aaa’: 1}
{‘bbb’: 1}

python解析和打包protobuf

概述

Protocol Buffers,简称protobuf或pb,是Google公司开发的一种数据描述语言,类似于XML和JSON能够将结构化数据序列化用于数据存储、通信协议等方面。目前官方支持C++、JAVA、Python等三种编程语言。

与XML和JSON相比,protobuf在配置时将数据key映射为递增数字,使用二进制传输,并能够根据schema自动生成各语言的打包、解析回kv的代码,非常方便各语言数据互通,且有以下优点
1. 数据文件只需原来的1/10至1/3  #相同的数据,大小只有json的1/10
2. 解析速度是原来的20倍至100倍
3. 通过递增数字做key传输value,减少了二义性,在接口发生变化时完全像后兼容
4. 非常容易自动生成各语言中使用的数据访问类,将数据key根据schema自动转回易理解的英文key

protobuf不是用来替代json和xml的,它最初的目的是为了更小的带宽占用、更快的传输速度,所以使用数据key+二进制传输,也产生了一些缺点

1. 对人不可读。(适合加密数据传输)
2. 不能发给web浏览器,比如js无法处理这种数据。(适合c、java、python语言开发的程序间共享数据)
3. 开发适配成本高,不适合schema经常变的场景。(适合公司内部各产品间相对通用稳定的协议通信)

安装和使用

前提:需要gcc, gcc-c++, make, build等编译环境

yum -y install gcc gcc-c++ libstdc++-devel make build

1. 下载protobuf源代码

# proto2用下边这个包
wget https://blog.yanjingang.com/wp-content/uploads/2016/09/protobuf-2.5.0.tar.gz
# proto3直接用最新release版即可:https://github.com/protocolbuffers/protobuf/releases
 wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.4/protobuf-all-3.11.4.tar.gz

*注:使用python3+proto2时,python的protobuf库版本兼容性问题能把人折麽死(proto2主要为python2开发,最后一次发布是14年,对python3的兼容性极差),建议别在这个事情上浪费时间了,如果当前用的proto2,要么升级proto版本到3,要么降python版本到2。

2. 解压,编译,安装

tar zxvf protobuf-3.11.4.tar.gz
cd protobuf-3.11.4
./configure
make
make check
make install

3. 安装完成,验证Linux命令

protoc --version
>>libprotoc 3.11.4

4. 继续安装protobuf的python模块(如果不用python,可跳过这一步)

cd ./python  
python setup.py build
python setup.py test
python setup.py install

5. 验证Python模块是否被正确安装

python
>>>import google.protobuf

6. 根据test.proto生成python类test_pb2.py

# 配置test.proto
syntax="proto3";
package test.abc;

//Test
message Test {
    string name = 1;
    uint32 speed = 2;
    State state = 3; 
    float time = 5;
    bytes content = 6;
    
    enum State { 
        STATE_OFF               = 0;
        STATE_STANDBY           = 1; 
        STATE_READY             = 2;
    }
};

# 生成pythhon类
protoc --python_out=./ ./test.proto  #--python_out=生成的python文件输出路径   对应的proto文件

7.解析测试

from test_pb2 import Test
test = Test()
test.name='A'
# 转pb
msg = test.SerializeToString()    #序列化这个message和以字符串的方式返回。 注意,这是二进行字节,不是一个文本; 我们只使用str类型作为一个方便的容器。
print(msg)
# 解析pb
test.ParseFromString(msg)    #从给出的字符串中解析一条message
print(test)

8.其他

如有前端js解析proto的需求,可以使用 protobuf.js 。

 

 

参考:

在Python中使用protocol buffers参考指南

https://github.com/protocolbuffers/protobuf/tree/master/src

google.protobuf.message

在Python 3.4里使用Protobuf 2.6

Language Guide (proto3)