zoukankan      html  css  js  c++  java
  • Python 线程和进程(2)

    IO操作不占用cpu
    计算占用cpu
     
    python多线程 不适合cpu密集操作类型的任务 适合IO操作密集型任务 
     
    简单一个进程实例:
    import multiprocessing #进程模块
    import time
    
    def run(name,proce):
        time.sleep(1)
        print("hello",name,proce)
    
    if __name__ == '__main__':
    
        for i in range(10):
            p = multiprocessing.Process(target=run,args=('liyang',i,))
            p.start()
        p.join()

    进程里面能起线程吗?当然可以:

    # -*- coding:utf-8 -*-
    # Author:Brownyangyang
    import multiprocessing
    import time
    import threading
    
    def threadtest():
        print(threading.get_ident())  ##获取线程号
    
    def run(name,proce):
        time.sleep(2)
        print("hello",name,proce)
        t = threading.Thread(target=threadtest,)
        t.start()
    
    if __name__ == '__main__':
    
        for i in range(5):
            p = multiprocessing.Process(target=run,args=('liyang',i,))
            p.start()
        p.join()

    关于进程号

    import multiprocessing
    import os
    
    def info(title):
        print(title)
        print("module name:",__name__)
        print("parent process:",os.getppid()) ##打印父进程
        print("process id:",os.getpid())  ##打印当前进程
        print("------------------------")
    def f(name):
        info("33[031;1mfunction f33[0m")
        print("hello",name)
    
    if __name__ == "__main__":
        info("33[032;1mmain process line33[0m")
        p = multiprocessing.Process(target=f,args=("liyang",))
        p.start()
        p.join()

    结果( 这个310进程是pycharm的进程):

    main process line
    module name: __main__
    parent process: 310
    process id: 47385
    ------------------------
    function f
    module name: __main__
    parent process: 47385
    process id: 47386
    ------------------------
    hello liyang
     
     
    进程间是无法通信,如果非要通信,有以下几种办法:
     
    一、使用进程Queue(这里不同于线程的queue)
    # -*- coding:utf-8 -*-
    # Author:Brownyangyang
    from multiprocessing import Process,Queue
    #这里导入的是multiprocessing的Queue模块,不是小写哦,小写queue是线程queue
    
    def f(qq):
        qq.put([42,None,'hello'])
    
    if __name__ == '__main__':
        q = Queue()
        p = Process(target=f,args=(q,)) #把实例化的队列传到子进程,通过这种方式实现进程间通信。而线程不需这么做。
        p.start()
        print(q.get())
        p.join()
        print("done")

    原理是子进程复制了一份数据,然后通过序列化和反序列化再同步给主进程,不同于线程里面的修改数据

    二、使用Pipes(管道)数据传递

    # Author:Brownyangyang
    from multiprocessing import Process,Pipe
    
    def f(conn):
        conn.send([42,None,'hello'])  ##子进程给父进程发消息
        conn.send([40,'liyang','bye'])
        print(conn.recv())
        conn.close()
    
    if __name__ == '__main__':
        parent_conn,clild_conn = Pipe() ##生成管道实例
        p = Process(target=f,args=(clild_conn,)) ##这个传哪个都行,也可以传parent_conn
        p.start()
        print(parent_conn.recv())
        print(parent_conn.recv())
        parent_conn.send('hahahhah')  ##父进程给子进程发消息
        p.join

    三、managers 实现数据共享

    # -*- coding:utf-8 -*-
    # Author:Brownyangyang
    
    from multiprocessing import Process,Manager
    import os
    
    def f(d,l):
        d[os.getpid()] = os.getpid()
        l.append(os.getpid())
        print(l)
    
    if __name__ == '__main__':
        with Manager() as manager:
            d = manager.dict()  #生成一个字典,可在多个进程间共享和传递
            l = manager.list(range(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)
            print(l)

    进程锁:虽然进程独立,但是屏幕对于进程是共享的,这个锁只是控制屏幕打印不出现混乱

    # -*- coding:utf-8 -*-
    # Author:Brownyangyang
    from multiprocessing import Process,Lock
    
    def f(lock,i):
        lock.acquire()
        print("process id",i)
        lock.release()
    
    if __name__ == '__main__':
        lock = Lock()
        for i in range(10):
            p = Process(target=f,args=(lock,i,))
            p.start()

    进程池

    在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
    Pool可以提供指定数量的进程供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。

    apply   同步
    apply_async  异步
     
    # -*- coding:utf-8 -*-
    # Author:Brownyangyang
    from multiprocessing import Process,Pool
    import time,os
    #import greenlet
    
    def Foo(i):
        time.sleep(2)
        print("in process",os.getpid())
        return  i+10  ##这个参数会作为Bar的参数传递给Bar,这个不是很理解
    
    def Bar(arg):
        print("-->exec done:",arg,os.getpid()) ##回调
    
    if __name__ ==  '__main__':
        pool = Pool(processes=5) ##允许进程池同时放入5个进程
        print("主进程",os.getpid())
        for i in range(10):
            pool.apply_async(func=Foo,args=(i,),callback=Bar) #并行,执行完Foo就会执行Bar,这个Bar是主进程执行的,PID和主进程一样
            #pool.apply(func=Foo,args=(i,)) 串行
    
        print('end')
        pool.close()
        pool.join()##进程池中进程执行完毕后再关闭,如果注释则主程序执行完就退出。

    这个callback为什么是主进程写而不是子进程写呢,因为主进程写数据库只要一个长连接,但是如果是子进程需要10个链接,无形拉低了代码效率

    结果打印:
    主进程 51590
    end
    in process 51592
    in process 51593
    in process 51591
    in process 51594
    in process 51595
    -->exec done: 12 51590
    -->exec done: 11 51590
    -->exec done: 13 51590
    -->exec done: 10 51590
    -->exec done: 14 51590
    in process 51593
    in process 51592
    in process 51594
    in process 51591
    in process 51595
    -->exec done: 15 51590
    -->exec done: 16 51590
    -->exec done: 18 51590
    -->exec done: 17 51590
    -->exec done: 19 51590
     
  • 相关阅读:
    jeecg错误集锦之hql查询问题 java.lang.IllegalStateException: No data type for node: org.hibernate.hql.internal.ast.tree.IdentNode
    jeecg错误集锦之hql查询问题 org.hibernate.hql.internal.ast.QuerySyntaxException: order_pay is not mapped [SELECT PayChannel as className ,count(PayChannel) FROM order_pay group by PayChannel]
    es6--解构赋值-对象
    es6--解构赋值
    es6--let和const命令
    es6--let和const命令
    vue双向绑定时添加.sync不起作用的原因
    构建父子组件时注意的问题
    小程序scroll-view组件补充
    css自定义属性
  • 原文地址:https://www.cnblogs.com/brownyangyang/p/8910868.html
Copyright © 2011-2022 走看看