zoukankan      html  css  js  c++  java
  • Python 3学习 ——Python 多进程、协程、编码

    Python 学习——Python 多进程、协程、编码

     写此博客 是为了激励自己,并且将自己的心得以及遇到的问题与人分享

    一、进程

      1.概述

      multiprocessing 包是 Python 中的多进程管理包。与 thread.Threading 类似,可以利用 multiprocessing 对象来创建一个进程。该 Processing 对象与 Thread 对象的用法相同,也有 start() run() join() 的方法。具体使用看下面代码实现。使用这些 API 的时候有如下几点注意事项:  

    •   十分有必要对每个 Process 对象调用 join() 方法,阻止进程成为僵尸进程的一个手段。在多线程中由于只有一个进程,所以不需要采用这种手段。
    •   两个进程之间不能够共享数据,如果想共享数据要有一个第三方来对两者进行沟通共享。优先使用 Pipe 和 Queue ,避免使用 Lock / Event / Semaphone / Condition 等同步方式。  
    •   Windows 系统下,要想启动一个子进程,必须加上 If __name__ == "__main__": ,进程相关的要写在这句下面。
     1 #author:"LFD"
     2 #date: 2018/6/8
     3 from multiprocessing import Process
     4 import time
     5 
     6 def f(name):
     7     time.sleep(1)
     8     print('hello',name,time.ctime())
     9 
    10 if __name__ == "__main__":
    11     p_list = []
    12     for i in range(3):
    13         p = Process(target=f,args=('liufeiduo',))    # 创建进程
    14         p_list.append(p)
    15         p.start()
    16     for p in p_list:
    17         p.join()
    18 
    19     print('jincheng end!')
    20 
    21 ''' # 运行结果:
    22 hello liufeiduo Fri Jun  8 11:15:46 2018
    23 hello liufeiduo Fri Jun  8 11:15:46 2018
    24 hello liufeiduo Fri Jun  8 11:15:46 2018
    25 jincheng end!
    26 '''
    creat jincheng_1

    上面是通过方法实现多进程;

    下面是通过调用类实现多进程;

     1 from multiprocessing import Process
     2 import time
     3 
     4 class MyProcess(Process):
     5     def __init__(self,name):
     6         super(MyProcess,self).__init__()
     7         self.name = name
     8     def run(self):
     9         time.sleep(1)
    10         print('hello',self.name,time.ctime())
    11 
    12 if __name__ == '__main__':
    13     p_list = []
    14     for i in range(3):
    15         p = MyProcess('liufeiduo')
    16         p.start()
    17         p_list.append(p)
    18 
    19     for p in p_list:
    20         p.join()
    21 
    22     print('end')
    creat jincheng_2

      2.进程关系 

     1 from multiprocessing import Process
     2 import os,time
     3 
     4 def info(title):
     5     print(title)
     6     print('module name:',__name__)
     7     print('parent process:',os.getppid())
     8     print('process id:',os.getpid())
     9 
    10 def f(name):
    11     pass
    12 
    13 if __name__ == '__main__':
    14     info('33[32;1mmain process line33[0m')
    15     time.sleep(5)
    16     p = Process(target=info,args=('bob',))
    17     p.start()
    18     p.join()
    19 
    20 
    21 
    22 ''' 运行结果:
    23 main process line
    24 module name: __main__
    25 parent process: 7708     7708 是Pycharm 在电脑上分得的进程ID
    26 process id: 13972
    27 bob
    28 module name: __mp_main__
    29 parent process: 13972
    30 process id: 6024
    31 
    32 '''
    jincheng relationship

      3.实现不同进程间的通信

      通过队列实现 ( queue ) :

     1 #author:"LFD"
     2 #date: 2018/6/9
     3 
     4 from multiprocessing import Process,Queue
     5 import time
     6 def f(q):
     7     q.put([42,2,'hello',])
     8     print('main q id:', id(q))
     9 
    10 
    11 if __name__ == '__main__':
    12     q = Queue()
    13     p_list = []
    14     print('main q id:',id(q))
    15 
    16     for i in range(3):
    17         p = Process(target=f,args=(q,))#args=(q,) 把q当作参数传入到子进程当中 就可以找到了
    18         p_list.append(p)
    19         p.start()
    20 
    21     print(q.get())  # 两个进程间数据相互独立 是取不出来的
    22     print(q.get())
    23     print(q.get())
    24     
    25 ''' 执行结果:
    26 main q id: 1806769092704
    27 main q id: 2077092271608
    28 [42, 2, 'hello']
    29 main q id: 2579859953200
    30 [42, 2, 'hello']
    31 main q id: 2635574990216
    32 [42, 2, 'hello']
    33 '''
    jincheng talk-Queue

      通过 Pipe 实现:

     1 from multiprocessing import Process,Pipe
     2 
     3 def f(conn):
     4     conn.send('约么')
     5 
     6     print(conn.recv())
     7     conn.close()
     8 
     9 if __name__ == '__main__':
    10     parent_conn,child_conn = Pipe()
    11     p = Process(target=f,args=(child_conn,))
    12     p.start()
    13     print(parent_conn.recv())
    14 
    15     parent_conn.send('')
    16     p.join()
    17 
    18 
    19 
    20 ''' 运行结果:
    21 约么
    22 23 '''
    jincheng talk-Pipe

       4.数据共享—— Manager

     1 from multiprocessing import Process, Manager
     2 
     3 def f(d, l,n):
     4     d[n] = '1'
     5     d['2'] = 2
     6     d[0.25] = None
     7     l.append(n)
     8     print(l)
     9 
    10 if __name__ == '__main__':
    11     with Manager() as manager:
    12         d = manager.dict()
    13 
    14         l = manager.list(range(5))
    15         p_list = []
    16         for i in range(10):
    17             p = Process(target=f, args=(d, l,i))
    18             p.start()
    19             p_list.append(p)
    20         for res in p_list:
    21             res.join()
    22 
    23         print(d)
    24         print(l)
    25         
    26         
    27 '''     执行结果:
    28 [0, 1, 2, 3, 4, 0]
    29 [0, 1, 2, 3, 4, 0, 1]
    30 [0, 1, 2, 3, 4, 0, 1, 2]
    31 [0, 1, 2, 3, 4, 0, 1, 2, 3]
    32 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
    33 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5]
    34 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6]
    35 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7]
    36 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8]
    37 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    38 {0: '1', '2': 2, 0.25: None, 1: '1', 2: '1', 3: '1', 4: '1', 5: '1', 6: '1', 7: '1', 8: '1', 9: '1'}
    39 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    jincheng talk-Manager

     二、协程

      协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程

      优点:

    •   无需线程上下文切换的开销  
    • 无需原子操作锁定及同步的开销方便切换控制流,简化编程模型
    • "原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。
    • 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

      缺点:

    • 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
    • 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

       1.通过 yeild 实现协程代码实例:

     1 #author:"LFD"
     2 #date: 2018/6/11
     3 import time
     4 import queue
     5 
     6 
     7 def consumer(name):
     8     print("--->starting eating baozi...")
     9     while True:
    10         new_baozi = yield
    11         print("[%s] is eating baozi %s" % (name, new_baozi))
    12         # time.sleep(1)
    13 
    14 
    15 def producer():
    16     r = con.__next__()
    17     r = con2.__next__()
    18     n = 0
    19     while n < 5:
    20         n += 1
    21         print("33[32;1m[producer]33[0m is making baozi %s" % n)
    22         con.send(n)
    23         con2.send(n)
    24         
    25 
    26 
    27 if __name__ == '__main__':
    28     con = consumer("c1")
    29     con2 = consumer("c2")
    30     p = producer()

      2.greenlet 是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator 。

     1 from greenlet import greenlet
     2 
     3 
     4 def test1():
     5     print(12)
     6     gr2.switch()# 跳转到 test2 去执行  switch 方法实现切换
     7     print(34)
     8     gr2.switch()# 再次跳转到test2 去执行了
     9 
    10 
    11 def test2():
    12     print(56)
    13     gr1.switch()# 跳转回 test1 执行
    14     print(78)
    15 
    16 
    17 gr1 = greenlet(test1)
    18 gr2 = greenlet(test2)
    19 gr1.switch()

      3.Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

     1 import gevent
     2 
     3 
     4 def func1():
     5     print('33[31;1m李闯在跟海涛搞...33[0m')
     6     gevent.sleep(2)
     7     print('33[31;1m李闯又回去跟继续跟海涛搞...33[0m')
     8 
     9 
    10 def func2():
    11     print('33[32;1m李闯切换到了跟海龙搞...33[0m')
    12     gevent.sleep(1)
    13     print('33[32;1m李闯搞完了海涛,回来继续跟海龙搞...33[0m')
    14 
    15 
    16 gevent.joinall([
    17     gevent.spawn(func1),
    18     gevent.spawn(func2),
    19     # gevent.spawn(func3),
    20 ])

     

    三、Python2 和 Python3 的编码

      编码:基本概念很简单。首先,我们从一段信息即消息说起,消息以人类可以理解、易懂的表示存在。我打算将这种表示称为“明

    文”(plain text)。对于说英语的人,纸张上打印的或屏幕上显示的英文单词都算作明文。

     

    其次,我们需要能将明文表示的消息转成另外某种表示,我们还需要能将编码文本转回成明文。从明文到编码文本的转换称为“编码”,从编码

    文本又转回成明文则为“解码”。

     

  • 相关阅读:
    ACM ICPC 2008–2009 NEERC MSC A, B, C, G, L
    POJ 1088 滑雪 DP
    UVA 11584 最短回文串划分 DP
    POJ 2531 Network Saboteur DFS+剪枝
    UVa 10739 String to Palindrome 字符串dp
    UVa 11151 Longest Palindrome 字符串dp
    UVa 10154 Weights and Measures dp 降维
    UVa 10271 Chopsticks dp
    UVa 10617 Again Palindrome 字符串dp
    UVa 10651 Pebble Solitaire 状态压缩 dp
  • 原文地址:https://www.cnblogs.com/jinzejun/p/9128782.html
Copyright © 2011-2022 走看看