Python的re模块中match、search、findall的区别

re是Python中用于正则表达式相关处理的类,这四个方法都是用于匹配字符串的,具体区别如下:

match:匹配string 开头,成功返回Match object, 失败返回None,只匹配一个。

search:在string中进行搜索,成功返回Match object, 失败返回None, 只匹配一个。

findall:在string中查找所有 匹配成功的组, 即用括号括起来的部分。返回list对象,每个list item是由每个匹配的所有组组成的list。

import re

s = 'f80adsa30da7aae'

r1 = re.match('\d', s) # 从头匹配
r2 = re.search('\d', s)
r3 = re.findall('\d', s)
print(r1)
print(r2)
print(r2.group())
print(r3)

s1 = 'life is short, i use python'
r4 = re.search('life(.*)python', s1)
print(r4.group(0))
print(r4.group(1))

python中如何将元组(tuple)、列表(list)展开

可迭代元素(列表, 元组, 生成器等)展开, 可以使用*

1、列表展开:

l = ['kanghee', 'nanako','ranglee']

print(*l) # 输出 kanghee nanako ranglee

1、元展开:

t = ('kanghee', 'nanako','ranglee')

print(*t) # 输出 kanghee nanako ranglee

 

Python中StringIO与BytesIO与区别

1、StringIO

StringIO 是io 模块中的类,在内存中开辟的一个文本模式的buffer,可以像文件对象一样操作它。当close 方法被调用的时候,这个buffer 会被释放。

好处:一般来说,磁盘的操作比内存的操作要慢的多,内存足够的时候,一般的优化思路是少落地,减少磁盘IO的过程,可以大大提高程序的运行速度。业务中单机情况可以使用StringIo或者BytesIO,多机就考虑使用 redis。
缺点:内存断电,buffer 中的数据会丢失,所以不建议存储很重要的数据,但可以存储日志之类的丢失也没有大影响的数据。

1.1、导入

from io import StringIO

1.2、方法

  • close():刷新和关闭流。
  • readline()、readlines()、read:读取。
  • writelines(lines):将多行数据列表写入到流中。不会自动添加行分隔符,因此提供的每一条行数据的最后通常都有行分隔符(即给的行数据本身在每一行后面有行分隔符)。
  • getvalue():获取全部内容
  • readable():返回True如果流是可读的,返回False,如果流不可读,并且引发OSError错误。
  • writable():返回True,如果流是可写的。如果返回False,write()和truncate()操作会引发OSError操作。
  • seekable():返回True,如果流支持随机访问。如果返回错误,那么seek(),tell()和truncate()函数被调用时会引发OSError。
  • seek():设定该文件的当前位置。
  • tell():返回流中游标的当前位置。
  • flush():刷新写缓冲区,这个操作对于只读流和非阻塞流不起作用。
from io import StringIO

f = StringIO()

# 返回 True True True
print(f.readable(), f.writable(), f.seekable())

f.write("hello\nPython")
f.seek(0)

# 返回 hello 读取1行。如果是readlines,返回一个列表 ['hello\n', 'Python']
print(f.readline())

# 读取一行后,文件指针移到了下行行首
f.tell()

# 不受文件指针影响,输出全部内容
print(f.getvalue())

f.close()

2、BytesIO

BytesIO 也是io模块中的类,内存中开辟的一个二进制模式的buffer,也可以像文件对象一样操作它,当close方法调用的时候,这个buffer也会被释放。

简单使用方法与StringIO 一样:

from io import BytesIO

f = BytesIO()

# 返回 True True True
print(f.readable(), f.writable(), f.seekable())

f.write("hello\nPython".encode('utf-8'))
f.seek(0)

# 返回 hello 读取1行。如果是readlines,返回一个列表 ['hello\n', 'Python']
print(f.readline())

# 读取一行后,文件指针移到了下行行首
f.tell()

# 不受文件指针影响,输出全部内容
print(f.getvalue())

f.close()

请注意,写入的不是str,而是经过UTF-8编码的bytes。

3、StringIO、BytesIO的区别

StringIO操作的只能是str数据,BytesIO操作的只能是二进制数据。

4、小结:

  StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口

Python中struct_time、Timestrap、String之间转换

在Python中,通常有这几种方式来表示时间:

1、时间戳(timestamp)

通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。返回时间戳方式的函数主要有time.time(),time.mktime()等。

2、格式化的时间字符串

UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。

3、元组(struct_time)方式

struct_time元组共有9个元素,返回struct_time的函数主要有time.gmtime(),time.localtime(),time.strptime()。下面列出这种方式元组中的几个元素:

索引(Index) 属性(Attribute) 值(Values)
0 tm_year(年) 比如2011
1 tm_mon(月) 1 – 12
2 tm_mday(日) 1 – 31
3 tm_hour(时) 0 – 23
4 tm_min(分) 0 – 59
5 tm_sec(秒) 0 – 61
6 tm_wday(weekday) 0 – 6(0表示周日)
7 tm_yday(一年中的第几天) 1 – 366
8 tm_isdst(是否是夏令时) 默认为-1

4、struct_time、Timestrap、String之间转换:

在Flask框架中利用Flask-mail实现电子邮件发送功能

很多Web应用需要在诸如用户注册、密码找回等过程中,进行用户身份的有效性认证。采用电子邮箱进行确认是一种常用的方式。Python标准库smtplib可以实现发送电子邮件的功能,Flask框架的Flask-mail包装了smtplib库,扩展了对电子邮件发送的支持。

1、Flask-mail安装

pip install flask-mail

2、Flask-mail初始化配置

Flask-Mail 连接到简单邮件传输协议 (Simple Mail Transfer Protocol, SMTP) 服务器,并把邮件交给这个服务器发送。这里以 QQ 邮箱为例配置。

MAIL_SERVER = 'smtp.qq.com'
MAIL_PORT = 465
MAIL_USE_SSL = True
MAIL_USE_TSL = False
MAIL_USERNAME = '624784978@qq.com'
MAIL_PASSWORD = '你的QQ邮箱的授权码' # 注意这里的密码不是QQ邮箱的登陆密码。

Flask-Mail 使用标准的 Flask 配置 API 进行配置,下面是一些常用的配置项:

配置项 说明
MAIL_SERVER 邮件服务器地址,默认为 localhost
MAIL_PORT 邮件服务器端口,默认为 25
MAIL_USE_TLS 是否启用传输层安全 (Transport Layer Security, TLS)协议,默认为 False
MAIL_USE_SSL 是否启用安全套接层 (Secure Sockets Layer, SSL)协议,默认为 False
MAIL_DEBUG 是否开启 DEBUG,默认为 app.debug
MAIL_USERNAME 邮件服务器用户名,默认为 None
MAIL_PASSWORD 邮件服务器密码,默认为 None
MAIL_DEFAULT_SENDER 邮件发件人,默认为 None,也可在 Message 对象里指定
MAIL_MAX_EMAILS 邮件批量发送个数上限,默认为 None
MAIL_SUPPRESS_SEND 默认为 app.testing,如果为 True,则不会真的发送邮件,供测试用

3、在Flask框架中初始化Flask-mail

from flask_mail import Message, Mail
from flask import Flask

app = Flask(__name__)
app.config.from_object("app.setting")

mail = Mail()
mail.init_app(app)

4、Flask-mail邮件模板

邮件模板存放在flask框架默认的模板地址:templates/email.html。内容如下:

<p>亲爱的 {{ nickname }},</p>
<p>点击<a
        href="http://www.88shuo.com">这里</a>可以重置你的密码
</p>
<p>如果无法点击,你也可以将下面的地址复制到浏览器中打开:</p>
<p>http://www.88shuo.com</p>
<p>你的,Nanako</p>
<p>
    <small>注意,请不要回复此邮件哦</small>
</p>

5、异步发送邮件

为了避免发送邮件过程中出现的延迟,我们把发送邮件的任务移到后台线程中,代码如下:

def send_async_email(app, msg):
    with app.app_context():
        try:
            mail.send(msg)
        except Exception as e:
            raise e


def send_mail(app, to, suject, template, **kwargs):
    msg = Message(suject, sender=app.config['MAIL_USERNAME'], recipients=[to])
    msg.html = render_template(template, **kwargs)
    thr = Thread(target=send_async_email, args=[app, msg])
    thr.start()

6、完整代码

from flask_mail import Message, Mail
from flask import Flask, render_template
from threading import Thread

app = Flask(__name__)
# 读取邮件配置
app.config.from_object("app.setting")

mail = Mail()
mail.init_app(app)


def send_async_email(app, msg):
    with app.app_context():
        try:
            mail.send(msg)
        except Exception as e:
            raise e


def send_mail(app, to, suject, template, **kwargs):
    # recipients:可以批量送邮件
    msg = Message(suject, sender=app.config['MAIL_USERNAME'], recipients=[to])
    msg.html = render_template(template, **kwargs)
    thr = Thread(target=send_async_email, args=[app, msg])
    thr.start()


@app.route('/')
def main():
    send_mail(app, 'simme@126.com', '测试', 'email.html', nickname='kanghee')
    return 'k'


if __name__ == '__main__':
    app.run(debug=True)

 

Python标准模块之dbm模块

在一些python小型应用程序中,不需要关系型数据库时,可以方便的用持久字典来存储名称/值对,它与python的字典非常类似,主要区别在于数据是在磁盘读取和写入的。另一个区别在于dbm的键和值必须是字符串类型。

1、创建持久词典

import dbm

db = dbm.open('person', 'c')
# 添加选项
db['name'] = 'nanako'
db['age'] = '18'
db['email'] = 'kanghee@yeah.net'

for key in db.keys():
    print(key, db[key])

# 保存,关闭
db.close()

dbm.open函数关于打开dbm的方式有三种:

标志 用法
C 打开文件对其读写,必要时创建该文件
W 打开文件对其读写,如果文件不存在,不会创建它
N 打开文件进行读写,但总是创建一个新的空白文件

2、访问持久字典

从open函数返回的对象视作一个字典对象。对值的存取方式如下:

db[‘key’] = ‘value’

value = db[‘key’]

删除值:

del db[‘key’]

遍历所有key:

for key in db.keys():
    print(key, db[key])

 

Python中property() 函数

它以一个函数形式,定义一个属性,与@property实现原理类似,或者就是它的的变异用法。

其原型为:

property(fget=None, fset=None, fdel=None, doc=None)

示例:

class Animal(object):
    def __init__(self, name, age):
        self._name = name
        self._age = age
        self._color = 'Black'

    def get_name(self):
        return self._name

    def set_name(self, value):
        if isinstance(value, str):
            self._name = value
        else:
            self._name = 'No name'

    name = property(fget=get_name, fset=set_name, fdel=None, doc='name of an animal')

    def get_age(self):
        return self._age

    def set_age(self, value):
        if value > 0 and value < 100:
            self._age = value
        else:
            self._age = 0
            # print 'invalid age value.'

    age = property(fget=get_age, fset=set_age, fdel=None, doc='name of an animal')


a = Animal('black dog', 3)
a.name = 'white dog'
a.age = 3
print('Name:' + a.name)
print(Animal.name.__doc__)
print('Age:' + str(a.age))

运行结果:

Name:white dog
name of an animal
Age:3

 

Mac下Python标准模块ctypes模块调用C动态库

利用 ctypes 模块调用 C 共享库

ctypes模块是Python内建的用于调用动态链接库函数的功能模块,一定程度上可以用于Python与其他语言的混合编程。由于编写动态链接库,使用C/C++是最常见的方式,故ctypes最常用于Python与C/C++混合编程之中。

ctypes 是 Python 标准库提供的一个模块,Python 2.3 版本以上支持该模块。ctypes 是 Python 高级外部函数接口,Python 通过它可以调用 C 语言编译的静态链接库和动态链接库。ctypes 支持多个平台,包括 Windows, Windows CE, Mac OS X, Linux, Solaris, FreeBSD, OpenBSD。

1、编写C代码

#include <stdio.h>

int add(int x, int y){
    return (x+y); 
}

2、编译动态链接库 

gcc add.c -fPIC -shared -o libAdd.so 或者  gcc -fPIC -shared -o libAdd.so  add.c

3、phthon导入动态链接库,调用C函数 

import ctypes

so = ctypes.CDLL('/Users/pan/Desktop/python/flask/libAdd.so')

num = so.add(7, 9)

print(num) # 输出:16

 

使用python来操作redis用法详解

一、redis

Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便,Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。从盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。

二、python操作redis

1、连接方式

redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类

import redis

r = redis.Redis(host='localhost', port=6379,db=0)
r.set('name', 'nanako')   #添加
print (r.get('name'))   #获取

2、连接池

redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

pool = redis.ConnectionPool(host='localhost', port=6379)
r = redis.Redis(connection_pool=pool)
r.set('name', 'nanako')   #添加
print (r.get('name'))   #获取

3、Python操作redis

3.1、String 操作:

redis中的String在在内存中按照一个name对应一个value来存储

3.1.1、set():在Redis中设置值,默认不存在则创建,存在则修改

set(name, value, ex=None, px=None, nx=False, xx=False)
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,同setnx(name, value)
xx,如果设置为True,则只有name存在时,当前set操作才执行

3.1.2、mset():批量设置值

#批量设置值
r.mset(name='nanako', age='18')
#或
r.mget({"name":'nanako', "age":'18'})

3.1.3、get(name):获取值
3.1.4、mget(keys, *args):批量获取

#批量获取
print(r.mget("name","age"))
#或
person=["name","age"]
print(r.mget(person)

3.1.5、getset(name, value):设置新值,打印原值

#设置新值,打印原值
print(r.getset("name","nanako")) #输出:nanako
print(r.get("name")) #输出:nanako

3.1.6、append(name, value):在name对应的值后面追加内容

#在name对应的值后面追加内容
r.set("name","nanako")
print(r.get("name"))    # 输出:'nanako
r.append("name","kanghee")
print(r.get("name"))    # 输出:nanakokanghee

3.1.7、getrange(key, start, end):根据字节获取子序列

#根据字节获取子序列
r.set("name","nanako")
print(r.getrange("name",0,3))  # 输出:nana

3.1.8、setrange(name, offset, value):修改字符串内容,从指定字符串索引开始向后替换,如果新值太长时,则向后添加

r.set("name", "nanako")
r.setrange("name", 1, "m")
print(r.get("name"))  # 输出:nmnako
r.setrange("name", 6, "pppppp")
print(r.get("name"))  # 输出:nmnakopppppp

3.1.9、strlen(name):返回name对应值的字节长度(一个汉字3个字节)

#返回name对应值的字节长度(一个汉字3个字节)
r.set("name","nanako")
print(r.strlen("name")) # 输出:6

3.1.10、incr(self, name, amount=1):自增mount对应的值,当mount不存在时,则创建mount=amount,否则,则自增,amount为自增数(整数)

print(r.incr("mount",amount=2))#输出:2
print(r.incr("mount"))#输出:3
print(r.incr("mount",amount=3))#输出:6
print(r.incr("mount",amount=6))#输出:12
print(r.get("mount")) #输出:12

3.2、Hash 操作

redis中的Hash 在内存中类似于一个name对应一个dic来存储

3.2.1、hset(name, key, value):name对应的hash中设置一个键值对(不存在,则创建,否则,修改)

r.hset("dic_name", "name", "nanako")

3.2.2、hget(name,key):在name对应的hash中根据key获取value

print(r.hget("dic_name", "name"))  # 输出:nanako

3.2.3、hgetall(name):获取name对应hash的所有键值

print(r.hgetall("dic_name"))

3.2.4、hmset(name, mapping):在name对应的hash中批量设置键值对,mapping:字典

dic = {"name": "nanako", "age": "18"}
r.hmset("dic_name", dic)
print(r.hget("dic_name", "name"))  # 输出:nanako

3.2.5、hmget(name, keys, *args):在name对应的hash中获取多个key的值

person = ["name", "age"]
print(r.hmget("dic_name", person))
print(r.hmget("dic_name", "name", "age"))

3.2.6、hlen(name)、hkeys(name)、hvals(name):在name对应的hash中获取多个key的值

dic = {"name": "nanako", "age": "18"}
r.hmset("dic_name", dic)

# hlen(name) 获取hash中键值对的个数
print(r.hlen("dic_name"))

# hkeys(name) 获取hash中所有的key的值
print(r.hkeys("dic_name"))

# hvals(name) 获取hash中所有的value的值
print(r.hvals("dic_name"))

3.2.7、hexists(name, key):检查name对应的hash是否存在当前传入的key

print(r.hexists("dic_name","name"))  # 输出:True

3.2.8、hdel(name,*keys):在name对应的hash中获取多个key的值

r.hdel("dic_name","name")

3.3、List 操作

redis中的List在在内存中按照一个name对应一个List来存储
3.3.1、lpush(name,values):在name对应的list中添加元素,每个新的元素都添加到列表的最左边

r.lpush("list_name", 2)
r.lpush("list_name", 3, 4, 5)  # 保存在列表中的顺序为5,4,3,2

3.3.2、rpush(name,values):同lpush,但每个新的元素都添加到列表的最右边
3.3.3、lpushx(name,values):在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
3.3.4、rpushx(name,values):在name对应的list中添加元素,只有name已经存在时,值添加到列表的最右边
3.3.5、rpushx(name,values):name对应的list元素的个数

print(r.llen("list_name"))

3.3.6、linsert(name, where, refvalue, value)):在name对应的列表的某一个值前或后插入一个新值

r.linsert("list_name","BEFORE","2","nanako")  # 在列表内找到第一个元素2,在它前面插入SS

'''参数:
     name: redis的name
     where: BEFORE(前)或AFTER(后)
     refvalue: 列表内的值
     value: 要插入的数据'''

3.3.7、lpop(name):移除列表的左侧第一个元素,返回值则是第一个元素

print(r.lpop("list_name"))

3.3.8、lindex(name, index):在name对应的列表的某一个值前或后插入一个新值

print(r.lindex("list_name",1))

3.3.9、lrange(name, start, end):分片获取元素

print(r.lrange("list_name",0,-1))

3.3.10、ltrim(name, start, end):移除列表内没有在该索引之内的值

r.ltrim("list_name",0,2)

3.4、Set 操作

Set集合就是不允许重复的列表
3.4.1、sadd(name,values):给name对应的集合中添加元素

r.sadd("set_name", "nanako")
r.sadd("set_name", "nanako", "kanghee")

3.4.2、smembers(name):获取name对应的集合的所有成员
3.4.3、smove(src, dst, value):将某个元素从一个集合中移动到另外一个集合
3.4.4、spop(name):从集合的右侧移除一个元素,并将其返回
3.4.5、srem(name, values):删除name对应的集合中的某些值

print(r.srem("set_name2","bb","dd"))

3.4.6、sunion(keys, *args):获取多个name对应的集合的并集

r.sunion("set_name","set_name1","set_name2")

4、其他常用操作

  • delete(*names):根据name删除redis中的任意数据类型
  • exists(*names):检测redis的name是否存在
  • keys(pattern=’*’):根据* ?等通配符匹配获取redis的name
  • expire(name ,time):为某个name设置超时时间
  • rename(src, dst):重命名
  • move(name, db)):将redis的某个值移动到指定的db下
  • randomkey():随机获取一个redis的name(不删除)
  • type(name):获取name对应值的类型

近期文章

近期评论

标签

随机文章