python abc模块_python重要模块学习一

包含:

1、利用SocketServer进行网络编程

2、IO多路复用 select

3、多线程 threading

4、抽象基类abc

5、inspect模块

1、利用SocketServer进行网络编程

网络编程最基础是 socket模块,下面介绍SocketServer模块,关于更多,参考

服务器端

#! /usr/bin/env python

#--*--coding:utf8--*--

from SocketServer import (TCPServer as TCP,StreamRequestHandler as SRH)

from time import ctime

HOST = ''

PORT = 21567

ADDR = (HOST, PORT)

class MyRequestHandle(SRH):

def handle(self):

print '...connected from :', self.client_address

self.wfile.write('[%s] %s' % (ctime(), self.rfile.readline()))

tcpServer = TCP(ADDR,MyRequestHandle)

print 'waiting for connecting'

tcpServer.serve_forever()

客户端

#! /usr/bin/env python

#--*--coding:utf8--*--

from socket import *

HOST = 'localhost'

PORT = 21567

BUFFER = 1024

ADDR = (HOST,PORT)

while True:

tcpclisock = socket(AF_INET,SOCK_STREAM)

tcpclisock.connect(ADDR)

data = raw_input('>')

if not data:

break

tcpclisock.send('%s\r\n' % data)

data = tcpclisock.recv(BUFFER)

if not data:

break

print data.strip()

tcpclisock.close()

2、IO多路复用 select

import select

import socket

import sys

HOST = 'localhost'

PORT = 5000

BUFFER_SIZE = 1024

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind((HOST, PORT))

server.listen(5)

inputs = [server, sys.stdin]

running = True

while True:

try:

# 调用 select 函数,阻塞等待

readable, writeable, exceptional = select.select(inputs, [], [])

except select.error, e:

break

# 数据抵达,循环

for sock in readable:

# 建立连接

if sock == server:

conn, addr = server.accept()

# select 监听的socket

inputs.append(conn)

elif sock == sys.stdin:

junk = sys.stdin.readlines()

running = False

else:

try:

# 读取客户端连接发送的数据

data = sock.recv(BUFFER_SIZE)

if data:

sock.send(data)

if data.endswith('\r\n\r\n'):

# 移除select监听的socket

inputs.remove(sock)

sock.close()

else:

# 移除select监听的socket

inputs.remove(sock)

sock.close()

except socket.error, e:

inputs.remove(sock)

server.close()

Linux select模块基本原理可以在高级IO中简单回顾,python中对select函数API做了简单修改,select.select(rlist, wlist, xlist[, timeout])

程序中 inputs = [server, sys.stdin]为读监听列表,列表中是需要监听的文件描述符。当某个准备就绪时,会返回三个列表readable, writeable, exceptional,否则一直等待。通过类似下列语句

for sock in readable:

# 建立连接

if sock == server:

轮询判断哪个描述符准备好,并进行相应操作。

select的不足

select优点之一就是跨平台的特性并且在描述符数量小时用起来很好。但也存在以下问题:

select需要遍历监视的文件描述符,并且这个描述符的数组还有最大的限制。随着文件描述符数量的增长,用户态和内核的地址空间的复制所引发的开销也会线性增长。即使监视的文件描述符长时间不活跃了,select还是会线性扫描。

为了解决这些问题,操作系统又提供了poll方案,但是poll的模型和select大致相当,只是改变了一些限制。目前Linux最先进的方式是epoll模型。

3、多线程 threading

两种创建线程方法:

1、继承Thread类,重写他的run方法

import threading, time, random

count = 0

class Counter(threading.Thread):

def __init__(self, lock, threadName):

'''@summary: 初始化对象。

@param lock: 琐对象。

@param threadName: 线程名称。

'''

super(Counter, self).__init__(name = threadName) #注意:一定要显式的调用父类的初始

化函数。

self.lock = lock

def run(self):

'''@summary: 重写父类run方法,在线程启动后执行该方法内的代码。

'''

global count

self.lock.acquire()

for i in xrange(10000):

count = count + 1

self.lock.release()

lock = threading.Lock()

for i in range(5):

Counter(lock, "thread-" + str(i)).start()

time.sleep(2) #确保线程都执行完毕

print count

这里要说明一下run方法 和start方法: 它们都是从Thread继承而来的,run()方法将在线程开启后执行,可以把相关的逻辑写到run方法中(通常把run方法称为活动[Activity]。);start()方法用于启动线程。

2、创建一个threading.Thread对象,在它的初始化函数(init)中将可调用对象作为参数传入

import threading, time, random

count = 0

lock = threading.Lock()

def doAdd():

'''@summary: 将全局变量count 逐一的增加10000。

'''

global count, lock

lock.acquire()

for i in xrange(10000):

count = count + 1

lock.release()

for i in range(5):

threading.Thread(target = doAdd, args = (), name = 'thread-' + str(i)).start()

time.sleep(2) #确保线程都执行完毕

print count

threading.Thread类的初始化函数原型:

def __init__(self, group=None, target=None, name=None, args=(), kwargs={})

参数group是预留的,用于将来扩展;

参数target是一个可调用对象(也称为活动[activity]),在线程启动后执行;

参数name是线程的名字。默认值为“Thread-N“,N是一个数字。

参数args和kwargs分别表示调用target时的参数列表和关键字参数

条件变量

多线程中条件变量应用也很广泛,用于两个线程之间对某个共享信息之间的通信,比如线程A中等待某条件为真,该条件在线程B中改变,当成真时,发送一个信号给线程A继续运行

import threading, time

class Hider(threading.Thread):

def __init__(self, cond, name):

super(Hider, self).__init__()

self.cond = cond

self.name = name

def run(self):

time.sleep(1) #确保先运行Seeker中的方法

self.cond.acquire() #b

print self.name + ': 我已经把眼睛蒙上了'

self.cond.notify()

self.cond.wait() #c

#f

print self.name + ': 我找到你了 ~_~'

self.cond.notify()

self.cond.release()

#g

print self.name + ': 我赢了' #h

class Seeker(threading.Thread):

def __init__(self, cond, name):

super(Seeker, self).__init__()

self.cond = cond

self.name = name

def run(self):

self.cond.acquire()

self.cond.wait() #a #释放对琐的占用,同时线程挂起在这里,直到被notify并重新占有琐。

#d

print self.name + ': 我已经藏好了,你快来找我吧'

self.cond.notify()

self.cond.wait() #e

#h

self.cond.release()

print self.name + ': 被你找到了,哎~~~'

cond = threading.Condition()

seeker = Seeker(cond, 'seeker')

hider = Hider(cond, 'hider')

seeker.start()

hider.start()

注意到,在seeker函数和Hider函数中都有一个self.cond.acquire(),就是说同一把锁获得了两次,这在一般的lock对象中会发生死锁,threadiong.Condition在内部维护一个RLock对象,

两者区别是:

这两种琐的主要区别是:RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。

threading中还有一个Event方法,可以实现和条件对象类似的功能,内部维护一个标识符来实现线程间的同步问题。

threading.Event() # 初始化一个Event

Event.wait([timeout])

堵塞线程,直到Event对象内部标识位被设为True或超时(如果提供了参数timeout)。

Event.set()

将标识位设为Ture

Event.clear()

将标识伴设为False。

Event.isSet()

判断标识位是否为Ture。

还有个常用的模块是Timer,可以指定时间间隔执行某个操作

def hello():

print "hello, world"

t = Timer(3, hello)

t.start() # 3秒钟之后执行hello函数。

4、抽象基类abc

参考来源 http://www.jianshu.com/p/19ed49293168

https://segmentfault.com/a/1190000007921371

python中并没有提供抽象类与抽象方法,但是提供了内置模块abc(abstract base class)来模拟实现抽象类。

抽象类,顾名思义,是在更高的逻辑层面上定义了函数API,比如将动物定义为一个抽象类,定义抽象方法 奔跑,叫声等,可以不作具体实现,二是其子类做相应实现,比如狗,鸡等各自实现自己的方法。

通过@abc.abstractmethod将方法声明为抽象方法,比如:

import abc

class PluginBase(object):

__metaclass__ = abc.ABCMeta

@abc.abstractmethod

def load(self, input):

"""Retrieve data from the input source and return an object."""

return

@abc.abstractmethod

def save(self, output, data):

"""Save the data object to the output."""

return

具体化抽象基类有以下两种方式,

1、继承

class SubclassImplementation(PluginBase):

def load(self, input):

return input.read()

def save(self, output, data):

return output.write(data)

if __name__ == '__main__':

print 'Subclass:', issubclass(SubclassImplementation, PluginBase)

print 'Instance:', isinstance(SubclassImplementation(), PluginBase)

继承方式的优点:直接从抽象基类派生子类有一个好处,除非子类实现抽象基类的抽象方法,否则子类不能实例化。

2、注册

class RegisteredImplementation(object):

def load(self, input):

return input.read()

def save(self, output, data):

return output.write(data)

PluginBase.register(RegisteredImplementation)

if __name__ == '__main__':

print 'Subclass:', issubclass(RegisteredImplementation, PluginBase)

print 'Instance:', isinstance(RegisteredImplementation(), PluginBase)

注册方式的缺点:不会出现在类的MRO (Method Resolution Order),故而也不能通过super()来调用抽象方法。当没有实现抽象方法时,实例化时候不会报错,只有在调用时候才会报错。

值得注意的是,抽象类的注册方法抽象类中 __metaclass__ = abc.ABCMeta,必不可少,否则报错无register方法。

注意,基类中抽象类的定义方法不会对其子类有强迫作用,比如抽象类为类方法,如下,继承子类对应方法可以是静态方法或一般方法。

class PluginBase(object):

__metaclass__ = abc.ABCMeta

@classmethod

@abc.abstractmethod

def load(cls, input):

"""Retrieve data from the input source and return an object."""

return

抽象属性

import abc

class Base(object):

__metaclass__ = abc.ABCMeta

@abc.abstractproperty

def value(self):

return 'Should never get here'

class Implementation(Base):

@property

def value(self):

return 'concrete property'

try:

b = Base()

print 'Base.value:', b.value

except Exception, err:

print 'ERROR:', str(err)

i = Implementation()

print 'Implementation.value:', i.value

输出为

ERROR: Can't instantiate abstract class Base with abstract methods value

Implementation.value: concrete property

5、inspect模块

官网说明为:

The inspect module provides several useful functions to help get information about live objects such as modules, classes, methods, functions, tracebacks, frame objects, and code objects. For example, it can help you examine the contents of a class, retrieve the source code of a method, extract and format the argument list for a function, or get all the information you need to display a detailed traceback.

There are four main kinds of services provided by this module: type checking, getting source code, inspecting classes and functions, and examining the interpreter stack.

用到的知识点:

inspect.getmembers(object[, predicate]):

import inspect

class test():

def __init__(self):

self.name = 'Yuan'

def meth(self):

pass

test = test()

res = inspect.getmembers(test)

print res

print dir(test)

输出结果:

[('__doc__', None), ('__init__', >), ('__module__', '__main__'), ('meth', >), ('name', 'Yuan')]

['__doc__', '__init__', '__module__', 'meth', 'name']

它会将dir()找到的名字对应的属性一并返回,形如[(name, value), ...]。另外,predicate是一个方法的引用,如果指定,则应当接受value作为参数并返回一个布尔值,如果为False,相应的属性将不会返回。使用is*(如isclass等)作为第二个参数可以过滤出指定类型的属性。在ryu源码中使用为:

clses = inspect.getmembers(mod, lambda cls: (inspect.isclass(cls) and

issubclass(cls, RyuApp) and

mod.__name__ ==

cls.__module__))

对mod对象中的每个模块,属性,方法,函数等根据第二个参数进行检查,当三个判断都为真才返回。

inspect.getcallargs()

Bind the args and kwds to the argument names of the Python function or method func, as if it was called with them.

from inspect import getcallargs

>>> def f(a, b=1, *pos, **named):

... pass

>>> getcallargs(f, 1, 2, 3)

{'a': 1, 'named': {}, 'b': 2, 'pos': (3,)}

>>> getcallargs(f, a=2, x=4)

{'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值