Jesse's home


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

43.Python之路 - 多进程实例及回调函数

发表于 2020-06-26 | 分类于 python , 06-Concurrent |

Python之路 - 多进程实例及回调函数

进程池实例 🍀

使用进程池维护固定数目的进程

server.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import socket
import os
import multiprocessing
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8080))
server.listen(5)
def talk(conn, client_addr):
print("Process pid : %s" % os.getpid())
while True:
try:
msg = conn.recv(1024)
if not msg:break
conn.send(msg.upper())
except Exception:
break
if __name__ == '__main__':
pool = multiprocessing.Pool()
while True:
conn, client_addr = server.accept()
# 同步则一时间只有一个客户端能访问,所以使用异步
pool.apply_async(talk,args=(conn, client_addr,))

client.py

1
2
3
4
5
6
7
8
9
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 8080))
while True:
msg = input("Please input message:").strip()
if not msg: continue
client.send(msg.encode('utf-8'))
data = client.recv(1024)
print(data.decode('utf-8'))
阅读全文 »

45.Python之路 - 并发编程之IO多路复用

发表于 2020-06-26 | 分类于 python , 06-Concurrent |

Python之路 - 并发编程之IO多路复用

前言 🍀

在网络编程中 , 如果服务端需要面临同时接收上千甚至上万次的客户端请求 , 利用 “进程池” 或 “线程池” 或许可以缓解部分压力 , 但是并不是一个好的选择 , 因为超过数量还是得等 ; 又或者线程一旦进行堵塞 ; 以及任务之间的高度独立 , 并不需要互相通信或者等待时 , 我们就需要用到I/O多路复用(IO Multiplexing) 了 , 又叫做事件驱动IO (Event driven IO)

I/O多路复用 🍀

I/O多路复用是指单个线程中 , 通过记录跟踪每个I/O流(sock)的状态 , 来同时管理多个I/O流

在I/O多路复用中只要一遇到IO就注册一个事件 , 然后主程序就可以继续干其他的事情了 , 直到IO处理完毕 , 继续恢复之前中断的任务 , 也就是说一个线程可以同时处理多个请求

举🌰

在UI编程中 , 常常要对鼠标点击进行响应 , 还要同时对键盘敲击也进行响应

多进程多线程方式 :

创建一个进程 , 进程中有两个线程 , 一个循环检测鼠标点击 , 一个循环检测键盘敲击 , 一旦检测到有情况就再开一个线程去处理 , 然后一直开下去……基本上是由创建进程/线程 , 维护进程/线程来解决的 , 这样对于CPU的资源是很浪费的

IO多路复用(事件驱动) :

创建一个事件(消息)队列 , 鼠标点击就往队列中增加一个鼠标点击事件 , 键盘敲击就往队列中增加一个键盘敲击事件 , 创建一个线程(IO线程)负责不断从队列中取出事件 , 根据不同的事件 , 调用不同的函数 , 如onClick() , onKeyDown()等 , 即一个线程解决了所有事件的问题 , 这就是复用

比较 : 与多进程多线程技术相比 , I/O多路复用最大的优势是系统开销小 , 系统不必创建进程/线程 , 也不必维护这些进程/线程 , 从而大大减小了系统的开销

目前常见支持I/O多路复用的系统调用select , poll , epoll ,I/O多路复用就是通过一种机制 , 一个进程可以监视多个描述符 , 一旦某个描述符就绪(一般是读就绪或者写就绪) , 能够通知程序进行相应的读写操作

而I/O多路复用的具体实现就是 , select , poll , epoll

阅读全文 »

44.Python之路 - 并发编程之协程

发表于 2020-06-26 | 分类于 python , 06-Concurrent |

Python之路 - 并发编程之协程

前言 🍀

在前面的文章中 , 基本已经可以解决并发编程中的基本问题了 , 但是如果我们要利用单线程来实现并发 , 线程是轻量级的进程 , 为了使计算机资源能更充分的利用 , 那么我们就需要用到协程了

并发的本质就是上下文切换加上保存状态 , 那么我们就可以想到关键字yield , 我们在生成器篇章中 , 就是利用了yield实现了状态的保存 , 来看一个廖大大的例子

生产者消费者模型yield版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import time
def consumer():
r = ''
time.sleep(1)
while True:
n = yield r
if not n:
return
time.sleep(1)
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
time.sleep(1)
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
'''
# yiled可以保存状态,yield的状态保存与操作系统的保存线程状态很像,但是yield是代码级别控制的,更轻量级
# send可以把一个函数的结果传给另外一个函数,以此实现单线程内程序之间的切换
'''

上述例子中yield确实实现了并发 , 但是并没有实现遇到IO操作进行自动切换 , 所以协程出场了

阅读全文 »

46.Python之路 - 实现线程池

发表于 2020-06-26 | 分类于 python , 06-Concurrent |

Python之路 - 实现线程池 🍀

方式一 🍀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import Queue
import threading


class ThreadPool(object):

def __init__(self, max_num=20):
self.queue = Queue.Queue(max_num)
for i in xrange(max_num):
self.queue.put(threading.Thread)

def get_thread(self):
return self.queue.get()

def add_thread(self):
self.queue.put(threading.Thread)

"""
使用:
pool = ThreadPool(10)

def func(arg, p):
import time
time.sleep(2)
p.add_thread()


for i in range(30):
thread = pool.get_thread()
t = thread(target=func, args=(i, pool))
t.start()
"""
阅读全文 »

11.Python之路 - Python函数

发表于 2020-06-07 | 分类于 python , 02-Advanced |

Python之路 - 函数

介绍 🍀

函数是组织好的 , 可重复使用的 , 用来实现单一 , 或相关联功能的代码段

函数能提高应用的模块性 , 和代码的重复利用率 , 比如我们一直使用的print() , input() 等等 , 都是函数

如下我们写了一个用户认证程序 ; 而现在我们又需要写一个用户管理系统 , 管理系统中有很多的功能 , 比如添加用户 , 删除用户 , 查询用户 , 修改用户 ; 但是这些功能必须先通过用户认证程序才能使用 , 明显我们不可能在每一个功能前加上一段用户认证代码 , 因为这将大大增加我们的重复代码

那么为了解决这个问题我们就可以将用户认证功能封装到一个函数之中 , 而后续我们如果需要使用这个函数仅需调用即可 , 着就是函数的魅力所在 , 当然更多的还是通过下面进一步了解函数

语法 🍀

1
2
3
4
5
6
7
8
9
# 自定义函数,function_name为函数名
def function_name():
"""注释"""

'''
功能代码块
'''
# 返回值,一般都具有返回值,当然也可以不设定
return result
阅读全文 »

12.Python之路 - Python函数进阶

发表于 2020-06-07 | 分类于 python , 02-Advanced |

Python之路 - 函数进阶

嵌套函数 🍀

嵌套函数即函数里面再套一个函数 , 如下 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 全局变量name
name = "Lyon_1"
def func():
# 第一层局部变量name
name = "Lyon_2"
print("第1层打印",name)

#嵌套
def func2():
# 第二层局部变量name
name = "Lyon_3"
print("第2层打印", name)

# 嵌套
def func3():
# 第三层局部变量
name = "Lyon_4"
print("第3层打印", name)
# 调用内层函数
func3()
# 调用内层函数
func2()
func()
print("最外层打印", name)
'''
执行结果:
第1层打印 Lyon_2
第2层打印 Lyon_3
第3层打印 Lyon_4
最外层打印 Lyon_1
'''
阅读全文 »

14.Python之路 - Python内置函数

发表于 2020-06-07 | 分类于 python , 02-Advanced |

Python之路 - 内置函数

str类型代码的执行(3个) 🍀

exec(object[, globals[, locals]]) 👈

将字符串当做表达式去执行,没有返回值

1
2
3
4
5
6
7
# 流程语句用exec
>>> exec("print('123')")
123
>>> exec('1+2+3+4')
10
>>> res = exec('1+2+3+4')
None

eval(expression, globals=None, locals=None) 👈

将字符串当做表达式去执行,并返回执行结果

1
2
3
4
# 简单求值表达式用eval
>>> res = eval('1+2+3+4')
>>> res
10

compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) 👈

阅读全文 »

15.Python之路 - Python迭代器和生成器

发表于 2020-06-07 | 分类于 python , 02-Advanced |

Python之路 - 迭代器和生成器

可迭代对象 🍀

在Python中一切皆对象

迭代是重复反馈过程的活动 , 其目的通常是为了逼近所需目标或结果

可迭代对象 , 即可以按照迭代的方式进行存取数据的对象 , 在python中我们可以理解为可以用for循环遍历的对象就是可迭代对象

for循环做的那些事 : for循环是我们用来遍历一个数据集合的方法 , 其实就是根据一定的要求 (这个要求叫做’协议’ ) 进行一次次的迭代的效果 . 当我们用for循环去遍历时 , 它做的第一件事就是判断对象是否是可迭代对象 , 如果是 , 那么它就会将该对象转换成一个迭代器 , 最后利用__next__()方法将迭代器中的内容一个接一个的取出来

可迭代对象的标志是 , 它具有__iter__()方法

判断对象是否为可迭代对象方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
# 导入模块
>>> from collections import Iterable
>>> l = ['lyon','oldboy']
# 判断是否为Iterable , 即可迭代对象
>>> isinstance(l,Iterable)
# 返回bool值
True

#或者下面这个方法也可以判断
l = ['lyon','oldboy']
print("__iter__" in dir(l))
>>> True
阅读全文 »

16.Python之路 - Python递归函数

发表于 2020-06-07 | 分类于 python , 02-Advanced |

Python之路 - 递归

递归算法 🍀

递归算法是一种直接或者间接地调用自身算法的过程(递归函数就是一个体现)。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简介而且易于理解。

特点:👈

  1. 递归就是再过程或函数里调用自身
  2. 再使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。递归算法解题通常显得很简洁,但递归算法解题的运行效率低
  3. 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序

要求:👈

  1. 每次调用在问题规模上都有所减少(通常是减半)
  2. 相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)
  3. 再问题的规模极小时必须要直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归条用将会称为死循环而不能正常结束
阅读全文 »

13.Python之路 - python匿名函数

发表于 2020-06-07 | 分类于 python , 02-Advanced |

Python之路 - 匿名函数

匿名函数介绍 🍀

lambda是一个表达式 , 而并非语句 , 所以可以出现在def语句所不能出现的位置 , 并且不需要指定函数名; lambda表达式还可以提高代码的可读性 , 简化代码

lambda表达式主要用于写一些简单的方法 , 对于复杂的还是用函数写的好

示例:

1
2
3
4
5
6
7
8
9
10
# 普通函数
def func(x):
return x * x
print(func(5))
-----------------------
# 匿名函数,自带return功能
func = lambda x : x * x
print(func(5))
---------------------------------------------------
func = lambda arguments : expression using argument
阅读全文 »
1…101112…21
Jesse

Jesse

求知若饥,虚心若愚.

209 日志
44 分类
41 标签
RSS
© Tue Jun 12 2018 08:00:00 GMT+0800 (GMT+08:00) — 2021 Jesse