zoukankan      html  css  js  c++  java
  • python——多进程

    python 其实是单线程程序,之所以有多线程是因为它是利用上下分时的功能让人感觉看起来是多线程。

    python 多线程不适合cpu密集操作性的任务,适合io操作密集的任务。

    多并发效果:

    import multiprocessing  
    import time
    def f(name):    
        print('hello', name)
     
    if __name__ == '__main__':  #注意这里的name==main,不是name==name
        for i in range(10):    
            p = multiprocessing.Process(target=f, args=(i,)) #定义多进程对象
            p.start()


    import multiprocessing也可以写成from multiprocessing import Process,但是下面使用的时候,就可以直接使用Process方法了。

    import time,threading
    import multiprocessing
    
    def thread_run():
        print threading.get_ident()   #得到线程号
    def run1(name):
        time.sleep(1)
        print 'hello',name
        t=threading.Thread(target=thread_run,)  #定义线程对象
        t.start()
    if __name__ == '__main__':  
        for i in range(10):
            p = multiprocessing.Process(target = run1 ,args=(i,))  #定义进程对象
            p.start()
    

    进程间通讯

    Queues:这里的Queues跟线程中的queue不是一样的,这里指的是from multiprocessing import  Queue进程中的Queue

    #coding:utf-8
    from multiprocessing import Queue,Process
    def run2(qq):
        qq.put('123')
    if __name__=='__main__':
        q=Queue()
        p=Process(target=run2,args=(q,))
        p.start()
        print q.get()
    

    Pipes(管道)

    跟socket的send、recv一样可以发送接收信息

    from multiprocessing import Process, Pipe
    def f(conn):
        conn.send([42, None, 'hello from child'])
        conn.send([42, None, 'hello from child2'])#双方可以互换的发送和接受信息。
        print("from parent:",conn.recv())
        conn.close()
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe()
        p = Process(target=f, args=(child_conn,))
        p.start()
        print(parent_conn.recv())  # prints "[42, None, 'hello']"
        print(parent_conn.recv())  # prints "[42, None, 'hello']"
        parent_conn.send("小王可好")
        p.join() #等待p进程的结束
    

    Managers

      Managersk可以实现列表,字典,命名空间,锁,rlock,semaphore,boundedsemaphore,condition,事件队列,势垒,和阵列数据的共享和修改。

    #coding:utf-8
    from multiprocessing import Process, Manager
    import os,time
     
    def f(d, l):
        d[1] = '1'
        d['2'] = 2
        d[0.25] = None
        l.append(os.getpid()) #将当期进程id添加到列表中
        print(l)
        time.sleep(2) 
    if __name__ == '__main__':
        with Manager() as manager:
            d = manager.dict()  #可在多个进程中共享数据的字典 
            l = manager.list(range(5))  #可在多个进程中共享5个数据的列表
            p_list = []
            for i in range(10):
                p = Process(target=f, args=(d, l))
                p.start()
                p_list.append(p)
            for res in p_list:
                res.join()  # 等待所有子进程执行完 
            print(d) #打印字典d
            print(l)   #打印列表l
    

    进程同步

    #coding:utf-8
    from multiprocessing import Process, Lock
     
    def f(l, i):
        l.acquire()  #加锁
        try:
            print('hello world', i)
        finally:
            l.release()  #释放锁
            print i
     
    if __name__ == '__main__':
        lock = Lock()
     
        for num in range(10):
            Process(target=f, args=(lock, num)).start()
    

    进程池  

    进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

    进程池中有两个方法:

    • apply  进程串行
    • apply_async   进程并行
    from  multiprocessing import Process,Pool
    import time,os
     
    def Foo(i):
        time.sleep(2)
        print 'foo is', os.getpid()
        return i+100 
    def Bar(arg):
        print('-->exec done:',os.getpid())
    if __name__=='__main__': #windows 必须加
        pool = Pool(3) #运行进程池同时放进3个数据      
        for i in range(10):
            pool.apply_async(func=Foo, args=(i,),callback=Bar) #callback回调,执行完foo,再调用Bar
            #pool.apply(func=Foo, args=(i,))    
        print('end',os.getpid())
        pool.close()
        pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
    

    结果:

    ('end', 22868)
    foo is 10768
    ('-->exec done:', 22868)
    foo is 22060
    ('-->exec done:', 22868)
    foo is 23728
    ('-->exec done:', 22868)
    foo is 10768
    ('-->exec done:', 22868)
    foo is 22060
    ('-->exec done:', 22868)
    foo is 23728
    ('-->exec done:', 22868)
    foo is 10768
    ('-->exec done:', 22868)
    foo is 22060
    ('-->exec done:', 22868)
    foo is 23728
    ('-->exec done:', 22868)
    foo is 10768
    ('-->exec done:', 22868)

  • 相关阅读:
    用.NET读取Flash格式文件信息
    通过ASP.NET页面重启服务器
    Webservice优点与缺点
    iClient 6R for Flex移动端开发的Q&A
    GIS十年路
    脚本调用命令行
    FME的简单介绍
    GIS从信息化到领域化(一)
    GIS从信息化到领域化(二)
    理性的看待地理信息共享交换平台建设
  • 原文地址:https://www.cnblogs.com/iexperience/p/9329362.html
Copyright © 2011-2022 走看看