• 进程与进程池


    一、开启进程的两种方式

    进程的定义:正在进行的一个过程或者说一个任务,是个抽象化的概念。

     在开启子进程开辟新空间时,子进程需要拷贝父进程中的数据。
    在 win 系统下,子进程会将父进程这个文件当成模块重新导入,需将发起开启子进程的操作放至main方法下;
    在linux系统下,则不需要将开启子进程放至 main 方法下,但是为了系统的兼容性,一般都是统一放至 main 方法下。

    方式一:

    from multiprocessing import Process
    import time
    
    
    def task(name):
        print('%s is running...' % name)
        time.sleep(3)
        print('%s is done ...' % name)
    
    
    if __name__ == '__main__':
        p = Process(target=task, args=('we',))  # target 是表示需要执行的函数
        # agrs() 括号里边传的参数(元组形式)是传入至 task 里边
        p.start()  # 仅仅是向操作系统发起了一个开启子进程的指令,并不是表示子进程已经开启完毕
        print('main Process')

    方式二:

     1 from multiprocessing import Process
     2 import time
     3 class MyProcess(Process):  # 自定义的一个进程(必须继承Process)
     4     def run(self):         # 这个是Process父类里边的一个绑定方法
     5         print("%s is running..."%self.name)
     6         time.sleep(3)
     7         print("%s is done"%self.name)
     8 
     9 
    10 if __name__ == '__main__':
    11     p=MyProcess()  # 实例化时需要用自己定义的类
    12     p.start()      # 向操作系统发起一个开启子进程的信号,但是并不表示子进程开启完 
    13                       # 毕(实际上是调用该子进程的p.run())
    14     print('main Process')

    二、进程(父进程和子进程)内存空间彼此隔离的验证

    1.进程间数据不共享

     1 from multiprocessing import Process
     2 import time
     3 x=100
     4 def task():
     5     global x   # 声明 x 为全局变量
     6     x=0
     7     print('I am done')
     8 if __name__ == '__main__':
     9     p=Process()
    10     p.start()
    11     time.sleep(3)   # 若是没有这一步,则<可能>子进程还未执行完成直接调至执行父        
    12                         # 进程的代码, 就是说,这一步是为了保证子进程能够顺利执行完成
    13     print(x)

    2.实现进程之间数据共享的方式

     1 from multiprocessing import Process,Manager
     2 import os
     3 def Foo(dic,list):
     4     dic[os.getpid()]=os.getpid()
     5     list.append(os.getpid())
     6     print(list)
     7 
     8 if __name__ == '__main__':
     9     with Manager() as manager:
    10         dic=manager.dict() # 造一个空字典,可以在多个进程键共享和传递
    11         list=manager.list() # 造一个空列表,可在多个进程间共享和传递
    12                             # 实际上是每次都将列表复制一份,然后往里边加值
    13         p_list=[]
    14         for i in range(10):
    15             p=Process(target=Foo,args=(dic,list))
    16             p.start()
    17             p_list.append(p)
    18         for p in p_list:
    19             p.join()
    20         print(dic)

    结果如下图

    三、进程对象方法或者属性

    1.join  (代表子进程的代码执行完毕)

     1 from multiprocessing import Process
     2 import time
     3 def task(name):
     4     print('%s is walking...'%name)
     5     time.sleep(3)
     6     print("%s is done..."%name)
     7 
     8 if __name__ == '__main__':
     9     p=Process(target=task,args=('BlackMan',))
    10     p.start()
    11     p.join()   # 代表子进程的代码已经执行完了
    12     print('main Process')

    2.多个子进程的运行

    from multiprocessing import Process
    import time
    def task(x,y):
        print('%s is running...'%x)
        time.sleep(y)
        print('%s is done...'%x)
    
    
    if __name__ == '__main__':
        p_list=[]
        start=time.time()
        for i in range(1,4):
            p=Process(target=task,args=('Processing-%s'%i,i))
            p_list.append(p)  # 这一步不要忘记写,否则直接执行父进程代码之后才开 
                                      # 始执行子进程代码
            p.start()    # p.start()写在这里的运行过程是多个子进程可以同时运行,可以 
                             #提高运行的效率
        for p in p_list:
            # p.start()    # p.start()如果写在这里运行过程就是先执行完一个子进程之 
                      # 后,再执行另一个子进程(就是串行的定义),这种执行方式效率比较低
            p.join()
        stop=time.time()
        print('creating Processing cost %s second'%(stop-start))
        print("it's turn to main Processing")

    2.pid   (2.1 os.getpid()--获取当前进程的 id ;os.getppid()--获取父进程的id)

       2.1需要用到 os 模块

    # getpid() 获取当前进程的id号
    # getppid() 获取父进程的id号
    from multiprocessing import Process
    import time,os
    def task(x):
        print("My id is %s..."%os.getpid())
        time.sleep(x)
        print('%s is gone...'%os.getpid())
    
    if __name__ == '__main__':
        p=Process(target=task,args=(3,))
        p.start()
        print(p.pid)   # 从父进程角度查看子进程的 id 号
        p.join()
        print('main Processing,%s'%os.getppid())

     四、进程池

     1 from multiprocessing import Pool
     2 import time,os
     3 
     4 def Foo(i):
     5     time.sleep(2)
     6     print('in the pool',os.getpid())
     7     return i+100
     8 
     9 def Bar(arg):
    10     print('exec done'.center(16,'-'),arg,os.getpid())
    11 
    12 if __name__ == '__main__':
    13     pool=Pool(processes=2)   # 允许进程池同时有4个进程
    14     print('---main---',os.getpid())
    15     for i in range(10):
    16         pool.apply_async(func=Foo,args=(i,),callback=Bar)
    17         # callback指向了回调函数(可用于记录日志)
    18         # pool.apply(func=Foo,args=(i,))  # 串行
    19         pool.apply_async(func=Foo,args=(i,))  # 并行
    20     print('end')
    21     pool.close()
    22 
    23     # 进程池中进程执行完毕后再关闭,若注释掉,那么程序则直接关闭
    24     pool.join()
  • 相关阅读:
    BZOJ-2743: [HEOI2012]采花(树状数组 or TLE莫队)
    BZOJ-1122: [POI2008]账本BBB (单调栈神题)
    2017年10月18日23:54:18
    [校内自测 NOIP模拟题] chenzeyu97要请客(单调栈)
    BZOJ-1057: [ZJOI2007]棋盘制作(单调栈)
    [校内自测] 奶牛编号 (递推+智商)
    [校内自测] Incr (LIS+智商)
    BZOJ1486 [HNOI2009]最小圈
    BZOJ2400 Spoj 839 Optimal Marks
    BZOJ2595 [Wc2008]游览计划
  • 原文地址:https://www.cnblogs.com/Smart1san/p/9295478.html
Copyright © 2020-2023  润新知