python自动化运维之路~DAY8

                      python自动化运维之路~DAY8

                                               作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

一.线程进程介绍

  为了方便我们队线程和进程的理解,我们来画2组图,方便我们对python中的线程和进程的理解。

其他语言线程与进程的关系如下图:

 

 

python语言线程与进程的关系如下图:

 

 

1.计算机工作最小单元是线程;

2.启动一个python可执行文件->应用程序->最少要有一个进程>最少要一有一个线程

3.应用场景:

    a>.IO密集型:线程

    b>.计算密集型:进程

4.GIL,全局解释器所。

    功能:保证同一个进程中只有一个线程同时被调用。(以上三点是所有语言的共同之处,只是PYTHON多了一个GIL规则而已。)

二.线程 

1.线程的基本使用

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #引入线程模块
 7 import  time  #引入时间模块
 8 
 9 def  test(arg):
10     time.sleep(1)  #执行该函数的时候让其睡上1s
11     print(arg)  #打赢传进来的位置参数
12     
13 for i in range(10):
14     t = threading.Thread(target=test,args=[i,]) #定义一个线程,并将2个值传进去;
15     t.start()  #启动该进程,标志着这个进程为准备状态,随时等待CPU执行。
16 
17 print("我是主线程")  #主线程
18 
19 
20 #以上代码执行结果如下:
21 我是主线程
22 3
23 2
24 0
25 4
26 8
27 7
28 6
29 1
30 5
31 9
32 
33 #经过试验证明,本来应该10s才能结束的脚本,但是用多线程运行的话只需要2s左右的时间就能搞定这个脚本,效率的确提高的不少!
写一个简单的线程
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #引入线程模块
 7 import  time  #引入时间模块
 8 
 9 def  test(arg):
10     time.sleep(arg)
11     print(arg)
12 
13 for i in range(10):
14     t = threading.Thread(target=test,args=[i,]) #定义一个线程,并将2个值传进去;
15     #t.setDaemon(True)  #主线程终止,不等待子线程,下面与其相反。
16     t.setDaemon(False)  #主线程终止,等待子线程,默认是需要等待的,所以这一行不写也可以。
17     t.start()  #启动该进程,标志着这个进程为准备状态,随时等待CPU执行。
18     t.join(2) #等待第一个线程执行完毕后再进行下一次循环,里面的参数表示等待的最大时间,如果不写的话就会一直等待当前循环的线程执行完毕后后再进行下一次循环,我们可以理解为等待最大时间。我这里让其最多等待2s的时间。
19 
20 print("我是主线程")  #主线程
21 
22 #以上代码执行结果如下:
23 0
24 1
25 2
26 3
27 4
28 5
29 6
30 我是主线程
31 7
32 8
33 9
线程中join的用法展示
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from threading import Thread
 7 
 8 def task(num,list):
 9     list.append(num)
10     print(list)
11 
12 if __name__ == '__main__':
13     v = []
14     for i in range(10):
15         p = Thread(target=task,args=(i,v))
16         p.start()
线程实现数据共享

 

2.线程任务被调用过程
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #导入线程模块
 7 import  time  
 8 
 9 class MyThread(threading.Thread): #继承了threading.Thread方法
10     def __init__(self,func,*args,**kwargs):
11         super(MyThread,self).__init__(*args,*kwargs) #实例化MyThread函数,也就是实例化它自己。
12         self.func = func
13     def run(self):
14         self.func(5) #传递的参数是5,意思是一会会睡5s
15 
16 def task(arg): #这个函数最最终被MyThread方法调用.
17     print("其实调用MyThread就是调用run方法哟~")
18     time.sleep(arg)
19     print("程序运行结束")
20 
21 obj = MyThread(func=task) #实例化
22 obj.start()
23 
24 
25 
26 #以上代码执行结果如下:
27 其实调用MyThread就是调用run方法哟~
28 程序运行结束
threading函数被调用的过程模拟展示
3.线程锁(注意:进程的锁跟其用法是一样的)
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #导入线程模块
 7 import  time
 8 '''
 9 前言:
10     我们在网上买商品的时候,卖家都有库存,当我们订单一个商品的时候就会让库存自减一,但是如果多个用户同时点击,
11 涉及到并发的时候,就需要对这个数据进行锁定,这一点尤其是在mysql数据库中尤为体现。那么它是如何实现的呢?
12 '''
13 stock = 10 #定义库存还剩下10件
14 lock = threading.Lock()  #设定一个锁
15 
16 def task(arg):
17     time.sleep(2)
18     lock.acquire()   #申请使用锁,其他人得排队等待。
19     global stock    #由于修改的是全局变量,需要用global方法声明一下
20     stock -= 1
21     print(stock)
22     lock.release()   #释放锁
23 
24 for i in range(10):
25     t = threading.Thread(target=task,args=(i,))
26     t.start()
27 
28 
29 #以上代码执行结果如下:
30 9
31 8
32 7
33 6
34 5
35 4
36 3
37 2
38 1
39 0
只能一个人使用的锁~Lock的用法展示
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #导入线程模块
 7 import  time
 8 '''
 9 前言:
10     我们在网上买商品的时候,卖家都有库存,当我们订单一个商品的时候就会让库存自减一,但是如果多个用户同时点击,
11 涉及到并发的时候,就需要对这个数据进行锁定,这一点尤其是在mysql数据库中尤为体现。那么它是如何实现的呢?
12 '''
13 stock = 10 #定义库存还剩下10件
14 #lock = threading.Lock()
15 lock = threading.RLock()  #设定一个递归锁
16 def task(arg):
17     time.sleep(2)
18     lock.acquire()   #锁一次
19     lock.acquire()   #再锁一次
20     global stock    #由于修改的是全局变量,需要用global方法声明一下
21     stock -= 1
22     print(stock)
23     lock.release()   #开第一层锁
24     lock.release()   #再开一层锁,要注意的是,只有Rlock才有递归解锁的功能,但是lock却没有这个功能,一点用lock被锁住2次,那么就会被彻底锁住。
25 
26 for i in range(10):
27     t = threading.Thread(target=task,args=(i,))
28     t.start()
29 
30 
31 #以上代码执行结果如下:
32 9
33 8
34 7
35 6
36 5
37 4
38 3
39 2
40 1
41 0
只能一个人使用的锁~递归锁RLock的用法展示
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #导入线程模块
 7 import  time
 8 '''
 9 前言:
10     我们在网上买商品的时候,卖家都有库存,当我们订单一个商品的时候就会让库存自减一,但是如果多个用户同时点击,
11 涉及到并发的时候,就需要对这个数据进行锁定,这一点尤其是在mysql数据库中尤为体现。那么它是如何实现的呢?
12 '''
13 stock = 20 #定义库存还剩下20件
14 lock = threading.BoundedSemaphore(5)  #表示同时能有5个人可以解开这个锁
15 def task(arg):
16 
17     lock.acquire()   #锁一次
18     time.sleep(1)
19     global stock    #由于修改的是全局变量,需要用global方法声明一下
20     stock -= 1
21     print(stock)
22     lock.release()   #开第一层锁
23 
24 for i in range(20):
25     t = threading.Thread(target=task,args=(i,))
26     t.start()
27 
28 
29 #以上代码执行结果如下:
30 19
31 18
32 17
33 16
34 15
35 14
36 13
37 12
38 11
39 10
40 9
41 8
42 7
43 6
44 5
45 4
46 3
47 2
48 1
49 0
多个人同时使用锁~BoundedSemaphore方法展示
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #导入线程模块
 7 import  time
 8 '''
 9 前言:
10     我们在网上买商品的时候,卖家都有库存,当我们订单一个商品的时候就会让库存自减一,但是如果多个用户同时点击,
11 涉及到并发的时候,就需要对这个数据进行锁定,这一点尤其是在mysql数据库中尤为体现。那么它是如何实现的呢?
12 '''
13 lock = threading.Event()  #创建一把事件锁
14 
15 def task(arg):
16     time.sleep(1)
17     lock.wait()  #锁住所有的线程
18     print(arg)
19 
20 for i in range(10):
21     t = threading.Thread(target=task,args=(i,))
22     t.start()
23 
24 while True:
25     value = input("please enter something>>>:")
26     if value == "1":
27         lock.set() #开锁,将之前用“lock.wait()”锁定的线程全部解开!
28        # lock.clear() #其实功能和"lock.set()"都标记而已,"lock.set()"表示可以开锁,而"lock.set()"表示锁定,所以默认情况下使用的就是"lock.set()"!
29 
30 
31 #以上代码执行结果如下:
32 please enter something>>>:1
33 please enter something>>>:5
34 1
35 9
36 3
37 7
38 2
39 0
40 4
41 8
42 6
全部锁定或解锁~事件锁Event用法展示
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 import threading  #导入线程模块
 7 import  time
 8 '''
 9 前言:
10     我们在网上买商品的时候,卖家都有库存,当我们订单一个商品的时候就会让库存自减一,但是如果多个用户同时点击,
11 涉及到并发的时候,就需要对这个数据进行锁定,这一点尤其是在mysql数据库中尤为体现。那么它是如何实现的呢?
12 '''
13 lock = threading.Condition()  #创建随机锁
14 
15 def task(arg):
16     time.sleep(1)
17     lock.acquire()
18     lock.wait()  #锁住所有的线程
19     print('线程:',arg)   #被锁定的代码
20     lock.release()
21 for i in range(10):
22     t = threading.Thread(target=task,args=(i,))
23     t.start()
24 
25 while True:
26     value = input("please enter something>>>:")
27     lock.acquire()
28     lock.notify(int(value))
29     lock.release()
30 
31 
32 
33 #以上代码执行结果如下:
34 please enter something>>>:1
35 please enter something>>>:线程: 1
36 2
37 please enter something>>>:线程: 2
38 线程: 0
39 3
40 please enter something>>>:线程: 3
41 线程: 4
42 线程: 5
43 4
44 please enter something>>>:线程: 7
45 线程: 8
46 线程: 9
47 线程: 6
48 5
49 please enter something>>>:6
50 please enter something>>>:
随机锁定或解锁的方法~Condition用法展示

 

 4.线程池

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
 7 import time
 8 import requests  #需要安装request模块,在windows的cmd窗口上执行:“C:\Users\尹正杰>pip3 install requests”即可。
 9 
10 pool = ThreadPoolExecutor(2)   #创建一个进程池,允许最大连接数为2
11 
12 def task(url):
13     response = requests.get(url)
14     print('统计网站的字节数为:',url,len(response.content))
15 
16 url_list = [
17     'http://www.cnblogs.com/yinzhengjie/',
18     'http://www.autohome.com.cn',
19     'http://www.baidu.com',
20     'http://www.sobaidupan.com/'
21 ]
22 
23 for url in url_list:
24     print('开始请求链接',url)
25     # 去连接池中获取链接
26     pool.submit(task,url)
27 
28 
29 #以上代码执行结果如下:
30 开始请求链接 http://www.cnblogs.com/yinzhengjie/
31 开始请求链接 http://www.autohome.com.cn
32 开始请求链接 http://www.baidu.com
33 开始请求链接 http://www.sobaidupan.com/
34 统计网站的字节数为: http://www.cnblogs.com/yinzhengjie/ 33024
35 统计网站的字节数为: http://www.baidu.com 2381
36 统计网站的字节数为: http://www.autohome.com.cn 1094712
37 统计网站的字节数为: http://www.sobaidupan.com/ 68175
并发发送Http请求,获取结果
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
 7 import time
 8 import requests  #需要安装request模块,在windows的cmd窗口上执行:“C:\Users\尹正杰>pip3 install requests”即可。
 9 
10 """
11 def task(host):
12     import paramiko
13     ssh = paramiko.SSHClient()
14     ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
15     ssh.connect(hostname=host, port=22, username='yinzhengjie', password='123')
16     stdin, stdout, stderr = ssh.exec_command('df')
17     result = stdout.read()
18     ssh.close()
19     print(result)
20 pool = ThreadPoolExecutor(2)
21 host_list = [
22     'c1.com',
23     'c2.com',
24     'c3.com',
25 ]
26 for host in host_list:
27     print('开始请求',host)
28     # 去连接池中获取链接
29     pool.submit(task,host)
30 """
31 def txt(future):
32     download_response = future.result()
33     print('处理中',download_response.url,download_response.status_code)
34 def download(url):
35     response = requests.get(url)
36     return response # response包含了下载的所有内容
37 pool = ThreadPoolExecutor(2)
38 url_list = [
39    'http://www.cnblogs.com/yinzhengjie/',
40     'http://www.autohome.com.cn',
41     'http://www.baidu.com',
42     'http://www.sobaidupan.com/',
43 ]
44 for url in url_list:
45     # 去连接池中获取链接
46     # 去下载吧
47     print('开始请求',url)
48     future = pool.submit(download,url)
49     # 下载完成之后,执行txt函数
50     future.add_done_callback(txt)
51 
52 
53 #以上代码执行结果如下:
54 开始请求 http://www.cnblogs.com/yinzhengjie/
55 开始请求 http://www.autohome.com.cn
56 开始请求 http://www.baidu.com
57 开始请求 http://www.sobaidupan.com/
58 处理中 http://www.cnblogs.com/yinzhengjie/ 200
59 处理中 http://www.baidu.com/ 200
60 处理中 http://www.autohome.com.cn/beijing/ 200
61 处理中 http://www.sobaidupan.com/ 200
并发远程主机并执行命令

 

三.进程

1.进程的基本使用

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from multiprocessing import Process  #导入进程模块
 7 import  time
 8 
 9 def task(arg):
10     time.sleep(5)
11     print(arg)
12 
13 if  __name__ == '__main__':
14     for i in  range(10):
15         p = Process(target = task, args = (i,))
16         p.daemon = True  #主线程执行完毕时,不等待子进程执行完毕就终止程序,下面与其相反。如果不设置的话默认为False!
17         #p.daemon = False
18         p.start()
19         p.join(2)  #每次循环等待子进程的执行时间为2s
20     print("我是主进程")  #主进程
21 
22 
23 #以上代码执行结果如下:(我们会发现当主进程执行完毕后,子进程就停止了,这都归功于“p.daemon = True”)
24 0
25 1
26 2
27 3
28 4
29 5
30 6
31 7
32 我是主进程
进程中daemon 与join的用法展示
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from multiprocessing import Process
 7 
 8 def task(num,list):
 9     list.append(num)
10     print(list)
11 
12 if __name__ == '__main__':
13     v = []
14     for i in range(10):
15         p = Process(target=task,args=(i,v))
16         p.start()
17 
18 #以上代码执行结果如下:
19 [1]
20 [0]
21 [2]
22 [3]
23 [4]
24 [5]
25 [6]
26 [7]
27 [8]
28 [9]
验证进程之间数据不共享(但线程可以实现数据共享,参考上面的案例)
2.进程之间实现数据共享
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from multiprocessing import Process,Array #调用类似C语音中的Array,其实就是定义一个数组。
 7 
 8 def task(num,list_1):
 9     list_1[num] = 1
10     print(list(list_1))
11 
12 if __name__ == '__main__':
13     v = Array('i',10)  #里面的参数对应的是“数据类型”和“长度”,所以其中的“i”这个“v”变量就是为了验证进程与进程之间的共享。
14     for i in range(10):
15         p = Process(target=task,args=(i,v))  #调用task函数并将“i”和"v"两个变量传递给task函数。
16         p.start()
17 
18 
19 #以上代码执行结果如下:
20 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
21 [0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
22 [1, 1, 0, 1, 0, 0, 0, 0, 0, 0]
23 [1, 1, 0, 1, 1, 0, 0, 0, 0, 0]
24 [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
25 [1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
26 [1, 1, 1, 1, 1, 1, 0, 1, 0, 0]
27 [1, 1, 1, 1, 1, 1, 1, 1, 0, 0]
28 [1, 1, 1, 1, 1, 1, 1, 1, 1, 0]
29 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Array实现进程的共享
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from multiprocessing import Process,Manager  #其中“Manager”是基于socket实现数据共享的。
 7 
 8 def task(num,list_1):
 9    list_1.append(num)
10    print(list_1)
11 
12 if __name__ == '__main__':
13     v = Manager().list()
14     #v = Manager().dict()
15     for i in range(10):
16         p = Process(target=task,args=(i,v))  #调用task函数并将“i”和"v"两个变量传递给task函数。
17         p.start()
18         p.join()  #不建议用join方法,进程还是变成了串行执行了,因为不用join的话会报错,无坑方便看到实现效果用join方法实现。
19 
20 
21 #以上代码执行结果如下:
22 [0]
23 [0, 1]
24 [0, 1, 2]
25 [0, 1, 2, 3]
26 [0, 1, 2, 3, 4]
27 [0, 1, 2, 3, 4, 5]
28 [0, 1, 2, 3, 4, 5, 6]
29 [0, 1, 2, 3, 4, 5, 6, 7]
30 [0, 1, 2, 3, 4, 5, 6, 7, 8]
31 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Manager实现进程间的数据共享

3.进程池

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from  concurrent.futures import ProcessPoolExecutor  #进程池和线程是都在concurrent这个模块里面
 7 
 8 def task(arg):
 9     print(arg)
10     return arg + 100
11 def call(arg):
12     data = arg.result()
13     print(data)
14 if __name__ == '__main__':
15     pool = ProcessPoolExecutor(5)
16     for i in range(10):
17         obj = pool.submit(task,i)
18         obj.add_done_callback(call)
19 
20 
21 #以上代码执行结果如下:
22 0
23 1
24 2
25 3
26 4
27 5
28 100
29 101
30 102
31 103
32 104
33 105
34 6
35 7
36 106
37 9
38 107
39 8
40 109
41 108
进程池案例展示

 

四.协程

  首先,明确一点,协程在计算机是不存在的,它不像线程和进程那样,在计算机中我们可以实际创建出来的东西!携程本质上就是一个线程(它可以将一根线程的工作效率发挥到极致。),只不过它可以让这个线程中的代码不依次执行,也就是说它可以来回切换一个线程中的代码,比如执行第一个函数的第一行代码突然跳到第三个函数的第一行代码,一会又跳到第四个函数的第二行代码,然后又跳转到第一行中的代码继续执行...。实现协程也有现成的模块,叫:greenlet,协程适合处理IO操作,单独执行一个协程其实没有任何意义的。 

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 '''
 7 扩展:
 8     Greenlet是python的一个C扩展,来源于Stackless python,旨在提供可自行调度的‘微线程’, 即协程。generator
 9 实现的协程在yield value时只能将value返回给调用者(caller)。 而在greenlet中,target.switch(value)可以切换到
10 指定的协程(target), 然后yield value。greenlet用switch来表示协程的切换,从一个协程切换到另一个协程需要显式
11 指定。
12 '''
13 from greenlet import greenlet  #需要安装模块,如果在linux环境中,我们打开cmd窗口执行:pip3 intsll greenlet即可。
14 def test1():
15     print("我是第一行",100)
16     gr2.switch()
17     print("我是第二行",200)
18     gr2.switch()
19 
20 def test2():
21     print("I'm the first line",300)
22     gr1.switch()
23     print("I'm the second line",400)
24 
25 gr1 = greenlet(test1) #创建一个‘微线程’,即协程,并不会有任何的输出。
26 gr2 = greenlet(test2)
27 gr1.switch() #“greenlet”用“switch”进行协程的切换
28 
29 
30 
31 #以上代码执行结果如下:
32 我是第一行 100
33 I'm the first line 300
34 我是第二行 200
35 I'm the second line 400

   协程也可以进行的二次加工,你可以对他自定义也可以用现成的gevent模块来实现。

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 from gevent import monkey;  monkey.patch_all()
 7 import gevent  #需要安装模块,在cmd窗口运行“pip3 install greenlet”即可。
 8 import requests
 9 
10 def f(url):
11     response = requests.get(url)
12     print(response.url,response.status_code)
13 
14 gevent.joinall([
15         gevent.spawn(f, 'http://www.cnblogs.com/yinzhengjie'),
16         gevent.spawn(f, 'http://www.baidu.com/'),
17         gevent.spawn(f, 'http://github.com/'),
18 ])
19 
20 #以上代码执行结果如下:
21 http://www.baidu.com/ 200
22 http://www.cnblogs.com/yinzhengjie 200
23 https://github.com/ 200

 

五.自定义异步非阻塞的框架。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值