内容目录:

  • python作用域
  • python2.7和python3.5的多继承区别
  • IO多路复用
  • socketserver模块源分析
  • 多线程、进程、协程

python作用域

 python中无块级作用域

if 1 == 1:
name = 'jabe' print(name)
#可以正常输出jabe #在python中无块级作用域
#在c#或者java中是不能这样使用的,提示name未定义的

python中以函数为作用域

def func():
name = 'jbae'
func()
print(name) #会提示name为定义的报错,说明在python中以函数为作用域的

 python作用域链由内想外找,直到找不到报错

name = 'jabe'
def f1():
# name = 'a'
def f2():
# name = 'b'
print(name)
f2()
f1() #输出
jabe

函数执行前,作用域(链)已经确定

name = 'jabe'

def f1():
print(name) def f2():
name = 'ljb'
f1() f2()
输出:
jabe
#===============================
name = 'jabe' def f1():
print(name) def f2():
name = 'ljb'
return f1 ret = f2()
ret()
输出:
jabe  

lambda函数作用域

li = [lambda :x for x in range(10)]
r = li[0]()
print(r)
print('===================')
#输出为9,上面的例子等同于下面的代码 li = []
for i in range(10):
def f1():
return i
li.append(f1)
#li 为列表,内部的元素为相同功能的函数
print(li[0]())
print(li[1]())
print(li[2]())
print(li[3]()) #输出:
# 9
# ===================
# 9
# 9
# 9
# 9

由于函数为被调用时是未被执行的,所以当循环结束时i为9,最后调用时候显示均为9

上面的函数我们稍作更改就可以打印的不为9了

li = []
for i in range(10):
def f1(x=i):
return x
li.append(f1) #li 为列表,内部的元素为相同功能的函数 print(li[0]())
print(li[1]())
print(li[2]())
print(li[3]()) #输出:
# 0
# 1
# 2
# 3

上面的例子中因为每次执行循环,将i值赋给x,因此打印的为0,1,2,3

python2.7和python3.5的多继承区别

我们从以前学过的知识中可以知道,python3.5类的多重继承顺序为从左到右,由下到上的顺序来继承寻找的。

在python2.7中,如果为新式类和py3.5中是寻找的顺序是一样的,但是经典类的继承顺序稍有不同,一直深层寻找,直到找到为止,不会向右边寻找。

不继承object是经典类,继承object是新式类 (和py3中一致)

IO多路复用

I/O多路复用指:通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。

python中有一个select模块,提供了select,poll,epoll三个方法

select:适用多平台,win+linux都可以,inputs 最多监控1024个对象,底层for 循环,效率不高

poll:适用多平台,inputs最多监控对象个数无限制,底层和select 一样都为for循环

epoll:适用于linux平台,底层采用触发机制,发生变化时通知,非循环遍历,效率要比select和poll要高很多

select方法说明:

句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间)

参数: 可接受四个参数(前三个必须)
返回值:三个列表 select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。
1、当 参数1 序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中
2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中
3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中
4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化
当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。

利用select 实现伪并发,同时处理多个客户端的请求:服务端

import socket
import select sk = socket.socket()
sk.bind(('127.0.0.1', 9999,))
sk.listen(5)
inputs = [sk,]
outputs = []
messages = {} while True:
rlist, wlist, elist = select.select(inputs,outputs,[sk],1)
print(len(inputs),len(rlist),len(outputs),len(wlist))
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,此时rlist值为【sk】
# 监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,此时rlist的值为 【客户端】
for r in rlist:
if r == sk:# 新客户来连接
conn,address = r.accept()# conn是什么?其实socket对象
inputs.append(conn)
messages[conn] = []
conn.sendall(bytes('Hello',encoding='utf-8'))
else: # 有人给我发消息了
print('====================')
try:
ret = r.recv(1024)
# r.sendall(ret)
if not ret:
raise Exception('断开连接')
else:
outputs.append(r)
messages[r].append(ret)
except Exception as e:
inputs.remove(r)
del messages[r] for w in wlist:# 所有给我发过消息的人
msg = messages[w].pop()
resp = msg + bytes('response', encoding='utf-8')
w.sendall(resp)
outputs.remove(w)

利用select 实现伪并发,同时处理多个客户端的请求:客户端  

import socket
sk = socket.socket()
ip_port = ('127.0.0.1',9999,)
sk.connect(ip_port)
data = sk.recv(1024)
print(data.decode())
while True:
inp = input(">>>")
sk.sendall(bytes(inp,encoding='utf-8'))
print(sk.recv(1024).decode()) sk.close()

通过上面的实例我们可以知道通过IO多路复用可以实现读写的分离,其实IO多路复用,并不是真正的多并发处理,只是底层循环接收消息,接收到进行处理的,不是同时接收多并发处理的,所以上面的例子称之为伪并发。真正的socketserver实现的了真正的并发,其他socketserver中还用的多线程、进程的使用,所以我们也可以通过多线程方式加上这种伪并发来实现socketserver的多并发的功能。

socketserver模块源分析

SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。

源码分析

我们通过一个简单例子来分析执行过程:

import socketserver

class MyClass(socketserver.BaseRequestHandler):

    def handle(self):
pass obj = socketserver.ThreadingTCPServer(('127.0.0.1', 9999), MyClass)
obj.serve_forever() 

socketserver 调用过程如下图:

内部调用流程为:

  • 启动服务端程序
  • 执行 TCPServer.__init__ 方法,创建服务端Socket对象并绑定 IP 和 端口
  • 执行 BaseServer.__init__ 方法,将自定义的继承自SocketServer.BaseRequestHandler 的类 MyRequestHandle赋值给self.RequestHandlerClass
  • 执行 BaseServer.server_forever 方法,While 循环一直监听是否有客户端请求到达 ...
  • 当客户端连接到达服务器
  • 执行 ThreadingMixIn.process_request 方法,创建一个 “线程” 用来处理请求
  • 执行 ThreadingMixIn.process_request_thread 方法
  • 执行 BaseServer.finish_request 方法,执行 self.RequestHandlerClass()  即:执行 自定义 MyRequestHandler 的构造方法(自动调用基类BaseRequestHandler的构造方法,在该构造方法中又会调用 MyRequestHandler的handle方法)

多线程、进程、协程

通过前面的学习我们可以知道,创建socket对象方式进行通讯默认是单进程单线程工作方式,而socketserver是通过多进程多线程的方式,在多线程中我们引用threding的模块。

threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

thread简单实例:

import threading
import time def f1(arg):
time.sleep(2)
print(arg) for i in range(10):
t1 = threading.Thread(target=f1,args=(i,))
t1.start()

上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。  

thread的其他方法:

  • start            线程准备就绪,等待CPU调度
  • setName      为线程设置名称
  • getName      获取线程名称
  • setDaemon   设置为后台线程或前台线程(默认)
  • 如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
  • 如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
  • join              逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
  • run              线程被cpu调度后自动执行线程对象的run方法
import threading
import time def f1(arg):
time.sleep(2)
print(arg) # for i in range(10):
# t1 = threading.Thread(target=f1,args=(i,))
# t1.start() t1 = threading.Thread(target=f1,args=(123,))
t1.setDaemon(True) #默认为False,设置为True表示主线程不等子线程
t1.start() #不代表当前线程会被立即执行
t1.join(1) #表示主线程到此等待。。。直到子线程执行完毕,参数表示主线程最多等待n秒 print('end')

python运维开发(十)----IO多路复用线程基本使用的更多相关文章

  1. python运维开发(十八)----Django(二)

    内容目录 路由系统 模版 Ajax model数据库操作,ORM 路由系统 django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对 ...

  2. python运维开发(十五)----JavaScript

    内容目录: HTML补充 javascript HTML补充 1.display标签 display的inline-block 属性会自动带3px的宽度 <span style="di ...

  3. python运维开发(十二)----rabbitMQ、pymysql、SQLAlchemy

    内容目录: rabbitMQ python操作mysql,pymysql模块 Python ORM框架,SQLAchemy模块 Paramiko 其他with上下文切换 rabbitMQ Rabbit ...

  4. python运维开发(十六)----Dom&&jQuery

    内容目录: Dom 查找 操作 事件 jQuery 查找 筛选 操作 事件 扩展 Dom 文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它 ...

  5. python运维开发(十四)----HTML基本操作

    内容目录: HTML概述 head标签 body中常用标签 css选择器 css常用属性 HTML HTML概述 HTML是英文Hyper Text Mark-up Language(超文本标记语言) ...

  6. python运维开发(十九)----Django后台表单验证、session、cookie、model操作

    内容目录: Django后台表单验证 CSRF加密传输 session.cookie model数据库操作 Django后台Form表单验证 Django中Form一般有2种功能: 1.用于做用户提交 ...

  7. Python运维开发基础09-函数基础【转】

    上节作业回顾 #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 实现简单的shell命令sed的替换功能 import ...

  8. Python运维开发基础07-文件基础【转】

    一,文件的基础操作 对文件操作的流程 [x] :打开文件,得到文件句柄并赋值给一个变量 [x] :通过句柄对文件进行操作 [x] :关闭文件 创建初始操作模板文件 [root@localhost sc ...

  9. Python运维开发基础10-函数基础【转】

    一,函数的非固定参数 1.1 默认参数 在定义形参的时候,提前给形参赋一个固定的值. #代码演示: def test(x,y=2): #形参里有一个默认参数 print (x) print (y) t ...

随机推荐

  1. PLSQL在cmd命令行中的基本用法

    首先:set serveroutput on:设置打印 declareresult number;beginselect (sal*12)+nvl(comm,0) into result from e ...

  2. [Head First Python]4. pickle.dump pickle.load

    sketch.py #--*-- coding:utf-8 --*-- import pickle import nester man = [] other = [] try: data = open ...

  3. Java所有编码问题参考手册

     一.编码基本知识 1.iso8859-1 ——属于单字节编码,最多能表示的字符范围是 0-255,应用于英文系列.比如,字母 'a' 的编码为0x61=97. 很明显,iso8859-1 编码表示的 ...

  4. 学习 ExtJS 4 面板与布局

    原文 http://www.cnblogs.com/codealone/archive/2013/06/04/3091325.html 面板Panel Ext.panel.Panel拓展自Ext.co ...

  5. Oracle 10g体系机构及安全管理《思维导图》

    通过学习Oracle数据库后,我对数据库又有了进一步的了解,Oracle数据库 10g体系机构分为 物理和逻辑存储结构. 下面是我对Oracle数据库做的思维导图和笔记 (全屏查看:<思维导图& ...

  6. python每次处理一个字符的三种方法

    python每次处理一个字符的三种方法 a_string = "abccdea" print 'the first' for c in a_string: print ord(c) ...

  7. UESTC_温泉旅店 CDOJ 878

    天空飘下一朵一朵的雪花,这是一片纯白的世界. 在天空之下的温泉旅店里,雪菜已醉倒在一旁,冬马与春希看了看说着梦话的雪菜,决定找一点玩的来度过这愉快的晚上. 这家旅店提供一种特色游戏,游戏有n张牌,各写 ...

  8. ios sourecTree

    1, http://www.jianshu.com/p/be9f0484af9d 2, http://blog.csdn.net/viewcode/article/details/42291973  

  9. 对Linux 专家非常有用的20 个命令

    谢谢你你给了我们在这篇文章前两个部分的喜欢,美言和支持.在第一部分文章中我们讨论了那些都只是切换到 Linux 和linux新手所需的必要知识的用户的命令. 对 Linux 新手非常有用的 20 个命 ...

  10. CHARINDEX (Transact-SQL)

    SQL Server 2014 其他版本 2(共 3)对本文的评价是有帮助 - 评价此主题 在一个表达式中搜索另一个表达式并返回其起始位置(如果找到). Transact-SQL 语法约定 语法   ...