Python学习第10天

事件驱动

简而言之,事件驱动分为二个部分:第一,注册事件;第二,触发事件。

自定义事件驱动框架

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #!/usr/bin/env python
 4 # -*- coding:utf-8 -*-
 5
 6 # event_drive.py
 7 event_list = []
 8 def run():
 9     for event in event_list:
10         obj = event()
11         obj.execute()
12 class BaseHandler(object):
13     """
14     用户必须继承该类,从而规范所有类的方法(类似于接口的功能)
15     """
16     def execute(self):
17         raise Exception(‘you must overwrite execute‘)

程序员使用上面定义的框架:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #!/usr/bin/env python
 4 # -*- coding:utf-8 -*-
 5
 6 from fram import event_drive
 7
 8 class MyHandler(event_drive.BaseHandler):
 9
10     def execute(self):
11         print (‘event-drive execute MyHandler‘)
12
13
14 event_drive.event_list.append(MyHandler)
15 event_drive.run()

Protocols

Protocols描述了如何以异步的方式处理网络中的事件。HTTP、DNS以及IMAP是应用层协议中的例子。Protocols实现了IProtocol接口,它包含如下的方法:

makeConnection               在transport对象和服务器之间建立一条连接
connectionMade               连接建立起来后调用
dataReceived                 接收数据时调用
connectionLost               关闭连接时调用

Transports

Transports代表网络中两个通信结点之间的连接。Transports负责描述连接的细节,比如连接是面向流式的还是面向数据报的,流控以及可靠性。TCP、UDP和Unix套接字可作为transports的例子。它们被设计为“满足最小功能单元,同时具有最大程度的可复用性”,而且从协议实现中分离出来,这让许多协议可以采用相同类型的传输。Transports实现了ITransports接口,它包含如下的方法:

write                   以非阻塞的方式按顺序依次将数据写到物理连接上
writeSequence           将一个字符串列表写到物理连接上
loseConnection          将所有挂起的数据写入,然后关闭连接
getPeer                 取得连接中对端的地址信息
getHost                 取得连接中本端的地址信息

将transports从协议中分离出来也使得对这两个层次的测试变得更加简单。可以通过简单地写入一个字符串来模拟传输,用这种方式来检查。

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from twisted.internet import protocol
 4 from twisted.internet import reactor
 5
 6 class Echo(protocol.Protocol):
 7     def dataReceived(self, data):#只要twisted一收到数据 ,就会调用此方法
 8         self.transport.write(data) # 把收到的数据 返回给客户端
 9
10 def main():
11     factory = protocol.ServerFactory() #定义基础工厂类
12     factory.protocol = Echo #socketserver中handle
13
14     reactor.listenTCP(9000,factory)
15     reactor.run()
16
17 if __name__ == ‘__main__‘:
18     main()
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 from twisted.internet import reactor, protocol
 4
 5 # a client protocol
 6
 7 class EchoClient(protocol.Protocol):
 8     """Once connected, send a message, then print the result."""
 9     def connectionMade(self): #连接建立成功,就会自动调用此方法
10         print("connection is build, sending data...")
11         self.transport.write("hello alex!")
12
13     def dataReceived(self, data):#一接收到数据就把它写回
14         "As soon as any data is received, write it back."
15         print "Server said:", data
16         #self.transport.loseConnection()
17         exit(‘exit‘)
18
19     def connectionLost(self, reason):#关闭连接
20         print "====connection lost==="
21
22 class EchoFactory(protocol.ClientFactory):
23     protocol = EchoClient  #handle
24
25     def clientConnectionFailed(self, connector, reason):
26         print "Connection failed - goodbye!"
27         reactor.stop()
28
29     def clientConnectionLost(self, connector, reason):
30         print "Connection lost - goodbye!"
31         reactor.stop()
32
33
34 # this connects the protocol to a server running on port 8000
35 def main():
36     f = EchoFactory()
37     reactor.connectTCP("localhost", 9000, f)
38     reactor.run()
39
40 # this only runs if the module was *not* imported
41 if __name__ == ‘__main__‘:
42     main()

运行服务器端脚本将启动一个TCP服务器,监听端口1234上的连接。服务器采用的是Echo协议,数据经TCP transport对象写出。运行客户端脚本将对服务器发起一个TCP连接,回显服务器端的回应然后终止连接并停止reactor事件循环。这里的Factory用来对连接的双方生成protocol对象实例。两端的通信是异步的,connectTCP负责注册回调函数到reactor事件循环中,当socket上有数据可读时通知回调处理。

一个传送文件的例子:

服务器端,

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 #_*_coding:utf-8_*_
 4 # This is the Twisted Fast Poetry Server, version 1.0
 5
 6 import optparse, os
 7
 8 from twisted.internet.protocol import ServerFactory, Protocol
 9
10
11 def parse_args():
12     usage = """usage: %prog [options] poetry-file
13
14 This is the Fast Poetry Server, Twisted edition.
15 Run it like this:
16
17   python twisted_sendfile.py <path-to-poetry-file>
18
19 If you are in the base directory of the twisted-intro package,
20 you could run it like this:
21
22   python twisted-server-1/fastpoetry.py poetry/ecstasy.txt
23
24 to serve up John Donne‘s Ecstasy, which I know you want to do.
25 """
26
27     parser = optparse.OptionParser(usage)
28
29     help = "The port to listen on. Default to a random available port."
30     parser.add_option(‘--port‘, type=‘int‘, help=help)
31
32     help = "The interface to listen on. Default is localhost."
33     parser.add_option(‘--iface‘, help=help, default=‘localhost‘)
34
35     options, args = parser.parse_args()
36     #print("--arg:",options,args)
37     #print("-->",options.port)
38
39     if len(args) != 1:
40         parser.error(‘Provide exactly one poetry file.‘)
41     poetry_file = args[0]
42
43     if not os.path.exists(args[0]):
44         parser.error(‘No such file: %s‘ % poetry_file)
45
46     return options, poetry_file
47
48
49 class PoetryProtocol(Protocol): #handle
50     def connectionMade(self):
51         self.transport.write(self.factory.poem)
52         self.transport.loseConnection()
53
54
55 class PoetryFactory(ServerFactory): #基础类
56     protocol = PoetryProtocol
57     def __init__(self, poem):
58         self.poem = poem
59
60 def main():
61     options, poetry_file = parse_args()
62     poem = open(poetry_file).read()
63     factory = PoetryFactory(poem)
64     from twisted.internet import reactor
65     port = reactor.listenTCP(options.port or 9000, factory,
66                              interface=options.iface)
67     print ‘Serving %s on %s.‘ % (poetry_file, port.getHost())
68     reactor.run()
69
70
71 if __name__ == ‘__main__‘:
72     main()

客户端:

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 # This is the Twisted Get Poetry Now! client, version 3.0.
 4
 5 # NOTE: This should not be used as the basis for production code.
 6
 7 import optparse
 8
 9 from twisted.internet.protocol import Protocol, ClientFactory
10
11
12 def parse_args():
13     usage = """usage: %prog [options] [hostname]:port ...
14
15 This is the Get Poetry Now! client, Twisted version 3.0
16 Run it like this:
17
18   python get-poetry-1.py port1 port2 port3 ...
19 """
20
21     parser = optparse.OptionParser(usage)
22     _, addresses = parser.parse_args()
23     print(‘==addr:‘,_,addresses)
24     if not addresses:
25         print parser.format_help()
26         parser.exit()
27
28     def parse_address(addr):
29         if ‘:‘ not in addr:
30             host = ‘127.0.0.1‘
31             port = addr
32         else:
33             host, port = addr.split(‘:‘, 1)
34         if not port.isdigit():
35             parser.error(‘Ports must be integers.‘)
36         return host, int(port)
37     #return  parse_address(addresses)
38     return map(parse_address, addresses)
39
40 class PoetryProtocol(Protocol):
41
42     poem = ‘‘
43     def dataReceived(self, data):
44         self.poem += data
45         #self.factory = PoetryClientFactory
46         print(‘[%s] recv:[%s]‘ %(self.transport.getPeer(),len(self.poem)))
47     def connectionLost(self, reason):
48         self.poemReceived(self.poem)
49
50     def poemReceived(self, poem):
51         self.factory.poem_finished(poem)
52
53
54 class PoetryClientFactory(ClientFactory):
55     protocol = PoetryProtocol #handle method
56     def __init__(self, callback):
57         self.callback = callback
58     def poem_finished(self, poem):
59         self.callback(poem)
60         #self.get_poem(poem)
61
62
63 def get_poetry(host, port, callback):
64     """
65     Download a poem from the given host and port and invoke
66       callback(poem)
67     when the poem is complete.
68     """
69     from twisted.internet import reactor
70     factory = PoetryClientFactory(callback)
71     reactor.connectTCP(host, port, factory)
72
73
74 def poetry_main():
75     addresses = parse_args() #((172.0.0.1,9000),(...))
76     from twisted.internet import reactor
77     poems = []
78
79     def got_poem(poem):
80         poems.append(poem)
81         if len(poems) == len(addresses):
82             reactor.stop()
83
84     for address in addresses:
85         host, port = address
86         get_poetry(host, port, got_poem)
87     reactor.run()
88
89     print("main loop done...")
90     #for poem in poems:
91     #    Eprint poem
92
93 if __name__ == ‘__main__‘:
94     poetry_main()

Redis:

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

Python操作Redis:

API使用

redis-py 的API的使用可以分类为:

  • 连接方式
  • 连接池
  • 操作
    • String 操作
    • Hash 操作
    • List 操作
    • Set 操作
    • Sort Set 操作
  • 管道
  • 发布订阅

1.基本操作

  之前我们已经知道,redis是以key-value的形式存储的,所以我们在操作的时候。首先我们将redis所在主机的ip和发布端口作为参数实例化了一个对象r,然后执行set(‘name‘,‘Peony_Y‘),这样我们就在内存中存储了一个key为name,值为‘Peony_Y’的项。我们可以理解为{‘name‘:‘Peony_Y‘},当我们要读取的之后,只需要get(‘name‘),就会得到‘Peony_Y‘的值。

2.连接池

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

3、管道

redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。

4、发布订阅

发布者:服务器

订阅者:Dashboad和数据处理

时间: 2024-10-12 13:25:52

Python学习第10天的相关文章

Python学习:10.Python装饰器讲解(一)

情景介绍 一天,在你正在努力加班的时候,老板给交给你了一个任务,就是在这段代码里将所有函数开始输出一个'hello'最后输出当前时间,再输出一个"end",这段代码里包含了大量的函数,你会怎么做? def f1(): print('proces a') def f2(): print('proces b') def f3(): print('proces c') def f4(): print('proces d') ... ... 刚拿到这个任务,我们可能想着这样做,在每个函数中添加

从零开始的Python学习Episode 10——函数

函数 一.函数的创建 简单格式 def function_name(参数表): 函数体 return 如果没有写return,函数会默认返回一个none 二.函数的参数 必需参数: 调用函数时必需参数须以正确的顺序传入,调用的数量必须和声明时的一样. def func1(name,age): print('my name is %s,i am %d years old'%(name,age)) func1('smilepup',20) #输出my name is smilepup,i am 20

python学习笔记10:python操作数据库(mysql、redis)

一.python操作mysql数据库 python3中操作mysql数据需要安装一个第三方模块,pymysql,使用 pip install pymysql 安装即可 二.python操作redis redis是一个nosql类型的数据库,数据都存在内存中,有很快的读写速度 python3中操作reids需要安装一个第三方模块,redis,使用 pip install redis 安装即可

python学习笔记10(用户交互程序)

注释 单行:# 多行:上下各用3个连续单引号或双引号 3个引号除了多行注释,还可以打印多行 举例: msg = name = (name) (msg) 运行结果第二个print就是打印3行字符串. 如果单行,用引号即可:msg = "Alex Li" python中,单引号和双引号相同,除了单套双或双套单. 例:msg = "I'm Alex Li" 用户输入 举例:  = () password = () (,password) 格式化输出 %s(string),

Python学习(10)元组

目录 Python 元组 访问元组 修改元组 删除元组 元组运算符 元组索引,截取 无关闭分隔符 元组内置函数 Python 元组 Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号. 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可. 如下实例: 创建空元组 tup1 = (); 元组中只包含一个元素时,需要在元素后面添加逗号 tup1 = (50,); 元组与字符串类似,下标索引从0开始,可以进行截取,组合等. 访问元组 元组可以使用下标

Python学习笔记10

? 1.函数式编程 ? 理论就来自lambda演算,虽然没有学过lisp,一直被其大名震撼. 特性: 函数是以一等公民 可以作为参数 可以作为返回值 具有闭包特性 ? 1.1参数传递方式 一般参数传递:值传递,引用传递 命名参数传递,使用"参数名=值"的格式,Python内成为关键字参数(keyword argument) 默认参数设置 可变参数,使用*开头,被解析成为一个元组 可变参数,使用**开头,被解析成为一个字典,必须使用关键字参数的方式 在调用的时候如何加上*,则会被解成元组

Python学习---8.10包的使用及loggin模块

一.包的使用 1.什么是包 包就是一个包含有__init__.py文件的文件夹 包本质就是一种模块,即包是用包导入使用的,包内部包含的文件也都是用来被导入使用的 2.为何要用包 包的本质就是一个文件夹,那么文件夹唯一的功能就是讲文件组织起来 随着功能越写越多,我们无法将所有功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性 首次导入包,发生三件事 1.以包下的__init__.py文件为基准来产生一个名称空

Python学习笔记10—几个名词概念

循环(loop),指的是在满足条件的情况下,重复执行同一段代码.比如,while 语句. 迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项.比如,for 语句. 递归(recursion),指的是一个函数不断调用自身的行为.比如,以编程方式输出著名的斐波纳契数列. 遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且每个节点都只访问一次. 迭代 我们常常将哪些能够用诸如循环语句之类的方法来一个一个读取元素的对象,就称之为可迭代的对象.那么用来循环的如 f

python基础教程_学习笔记10:异常

异常 什么是异常 Python用异常对象来表示异常情况.遇到错误后,会引发异常.如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行: >>> 1/0 Traceback (most recent call last): File "<pyshell#0>", line 1, in <module> 1/0 ZeroDivisionError: integer division or modulo by