python主线程执行回调函数_python异步回调函数的实现 | 学步园

说到异步回调函数的应用,最经典的就是ajax。

首先我们回想一下ajax是如何工作的。

variable=new XMLHttpRequest();

xmlhttp.onreadystatechange=function(){

if (xmlhttp.readyState==4 && xmlhttp.status==200){

document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

}

}

xmlhttp.open("GET","test1.txt",true);

xmlhttp.send();

这是一个经典的ajax使用方式,创建对象后为对象绑定回调函数,然后发送请求到远程服务器,由于是异步,所以继续往下执行,当远程服务器返回的时候,调用绑定的回调函数。

这里我们看到浏览器为我们做了一些事情,1、发送请求到远程服务器,2、监听远程服务器的返回,并且根据返回找到了对应的回调函数,然后执行。

实际上这里可以分成3个模型,一是脚本执行流程,二是浏览器底层,三是远程服务器。

而且为了实现python的异步回调函数也需要这三个模型。

根据自己的需要,我做了3个模型。

1是监听器listener,相当于浏览器底层。

作用是:监听7800端口

负责接收来自YoSQL服务器的回复

然后解析协议,得到回调函数的ID,通知逻辑进程执行回调函数

从YoSQL服务器发来的协议格式是“[id]message”,字符串表示

2是逻辑进程main,相当于脚本执行流程

作用是:

执行逻辑

发送消息和回调函数ID到YoSQL服务器,端口3316

执行逻辑

当收到YoSQL服务器的回复的时候执行回调函数

执行逻辑

。。。。

从逻辑进程发送到YoSQL服务器的协议是“[id]message”,字符串表示

3是YoSQL服务器,相当于远程服务器

作用是:监听3316端口

接收消息,解析协议,休眠2秒,回复监听器7800端口

YoSQL是一个独立的进程。为了简化开发,我将listener和main放到一个进程里面,分为2个线程来执行。当然你也可以用C来实现listener,C和python能够共享对象,实现起来也方便。

下面直接贴代码吧。

YoSQL代码

#-*-coding:utf-8-*-

from socket import *

import time

def main():

HOST = ""

PORT = 3316

BUFSIZE = 1024

ADDR = (HOST, PORT)

tcpSerSock = socket(AF_INET, SOCK_STREAM)

tcpSerSock.bind(ADDR)

tcpSerSock.listen(5)

print "YoSQL bind port %d ,starting ...." % PORT

while 1:

print 'waiting for connection ...'

tcpCliSock, addr = tcpSerSock.accept()

print '...connected from:',addr

while 1:

try:

data = tcpCliSock.recv(BUFSIZE)

if not data:

break

print 'data = %s' % data

i = data.find('[')

j = data.find(']')

if i!=-1 and j!=-1:

sFuncId = data[i+1:j]

message = data[j+1:]

time.sleep(2)

SendToListener("[%s] echo" % sFuncId)

except Exception, e:

print e

break

tcpCliSock.close()

tcpSerSock.close()

def SendToListener(message):

listenerSock = socket(AF_INET, SOCK_STREAM)

listenerSock.connect(('localhost',7800))

listenerSock.send(message)

listenerSock.close()

print 'send to listener: %s' % message

if __name__ == '__main__':

main()

listener和main代码:

#-*-coding:utf-8-*-

import threading

import time

from socket import *

lCallback = {}

iFuncId = 0

def StartListener():

global iFuncId

global lCallback

HOST = ""

PORT = 7800

BUFSIZE = 1024

ADDR = (HOST, PORT)

tcpSerSock = socket(AF_INET, SOCK_STREAM)

tcpSerSock.bind(ADDR)

tcpSerSock.listen(5)

print "Listener bind port %d ,starting ...." % PORT

while 1:

print 'waiting for connection ...'

tcpCliSock, addr = tcpSerSock.accept()

print '...connected from:',addr

while 1:

try:

data = tcpCliSock.recv(BUFSIZE)

if not data:

break

print 'data = %s' % data

i = data.find('[')

j = data.find(']')

if i!=-1 and j!=-1:

iFuncId = int(data[i+1:j])

message = data[j+1:]

func = lCallback.get(iFuncId,None)

if func:

func()

del lCallback[iFuncId]

except Exception,e:

print e

break

tcpCliSock.close()

tcpSerSock.close()

def MyCallback():

print 'callback called !!!!!!!!!!'

def Send(callback,message):

global iFuncId

global lCallback

lCallback[iFuncId] = callback

listenerSock = socket(AF_INET, SOCK_STREAM)

listenerSock.connect(('localhost',3316))

listenerSock.send("[%d] %s" % (iFuncId,message))

listenerSock.close()

iFuncId += 1

print 'send message to YoSQL : %s'%message

def DoSomeThing():

print '......DoSomeThing......'

if __name__ == '__main__':

t = threading.Thread(target=StartListener)

t.setDaemon(True)

t.start()

# t.join()

DoSomeThing()

DoSomeThing()

Send(MyCallback,"hahaha")

i = 0

while i < 20:

i+= 1

DoSomeThing()

try:

time.sleep(0.5)

except Exception,e:

print e

break

# t.join(2)

print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'

下面是执行结果图:

可以看到发送信息到远程服务器之后主逻辑继续往下执行,并没有阻塞,当远程服务器返回的时候回调函数被执行了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值