码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • python多进程(类成员函数、log在多进程中使用、自己维护进程池)


    写这篇的原因参考之前写的一篇博客Python 多进程池中子进程挂了导致进程不能结束的问题小结_文锦渡的博客-CSDN博客_python 子进程不能退出问题:Python multiprocessing pool not shutting down while child processes is oom开篇点题:在使用python的multiprocessing中的pool时,会出现子进程因为各种原因挂了之后主进程任务停不下来的情况。这是因为主进程没能发现子进程挂了而判定结束,从而卡在了这个地方,是python的一个bug。解决办法有两个,且看下文分解~https://blog.csdn.net/mxdsdo09/article/details/119728373?spm=1001.2014.3001.5501

     主要是为了记录自己实现的

    1、python进程池维护

    2、logging在多进程中的使用

    3、调用类的成员函数实现多进程

    一、调用类的成员函数实现多进程

    下面这部分代码是调用python自带的multiprocessing.Pool的进程池实现的对类的成员函数的调用,优点是方便快捷,但缺点在开头的另一篇文章里提到了 无法判断OOM和子进程GG 主进程会一直运行 不能中断

    1. import os
    2. import sys
    3. import time
    4. import multiprocessing
    5. class PrintNumber():
    6. def __init__(self, multi_num):
    7. self.multi_num = multi_num
    8. def run_task(self):
    9. sum_num = 1
    10. for i in range(5):
    11. sum_num += i
    12. time.sleep(1)
    13. print("multi_num = {}, output = {}".format(self.multi_num, sum_num))
    14. if __name__ == "__main__":
    15. print("multiprocess test")
    16. process_pool = multiprocessing.Pool(3)
    17. for i in range(3):
    18. test = PrintNumber(i)
    19. process_pool.apply_async(test.run_task, args=())
    20. print("main thread")
    21. test_main = PrintNumber(10)
    22. test_main.run_task()
    23. process_pool.close()
    24. process_pool.join()
    25. print("thread join success!")

    注意!process_pool.apply_async(test.run_task, args=())不要在test.run_task后加括号(test.run_task()),否则不会报错且输出相当于一个进程。。。原因懂得得大佬可以解释一下~

    输出

    1. #python3 test.py
    2. multiprocess test
    3. main thread
    4. multi_num = 2, output = 1
    5. multi_num = 1, output = 1
    6. multi_num = 10, output = 1
    7. multi_num = 0, output = 1
    8. multi_num = 2, output = 2
    9. multi_num = 0, output = 2
    10. multi_num = 1, output = 2
    11. multi_num = 10, output = 2
    12. multi_num = 2, output = 4
    13. multi_num = 1, output = 4
    14. multi_num = 0, output = 4
    15. multi_num = 10, output = 4
    16. multi_num = 1, output = 7
    17. multi_num = 2, output = 7
    18. multi_num = 0, output = 7
    19. multi_num = 10, output = 7
    20. multi_num = 1, output = 11
    21. multi_num = 2, output = 11
    22. multi_num = 0, output = 11
    23. multi_num = 10, output = 11
    24. thread join success!

    这里做了个验证,得for循环给PrintNumber实例化同一个名称test不会导致进程运行异常(原因暂时不清楚,感觉后面给test赋值应该会覆盖前面先实例化的呀?)

    二、自己构建进程池实现

    加入对进程数量和结果的判断,防止子进程挂了没能发现

    1. import os
    2. import sys
    3. import time
    4. import multiprocessing
    5. import logging
    6. # 全局变量在多进程中使用
    7. global g_log
    8. g_log = None
    9. def init_log(log_file):
    10. log = logging.getLogger() # 不加名称设置root logger
    11. log.setLevel(logging.DEBUG)
    12. formatter = logging.Formatter("%(asctime)s<%(levelname)s>: %(message)s",
    13. datefmt="%Y-%m-%d %H:%M:%S")
    14. # 使用FileHandler输出到文件
    15. fh = logging.FileHandler(log_file)
    16. fh.setLevel(logging.DEBUG)
    17. fh.setFormatter(formatter)
    18. # 使用StreamHandler输出到屏幕
    19. ch = logging.StreamHandler()
    20. ch.setLevel(logging.DEBUG)
    21. ch.setFormatter(formatter)
    22. # 添加两个Handler
    23. log.addHandler(ch)
    24. log.addHandler(fh)
    25. log.info("init log success!")
    26. return log
    27. class PrintNumber():
    28. def __init__(self, multi_num):
    29. self.multi_num = multi_num
    30. def run_task(self, thread_q):
    31. thread_id = os.getpid()
    32. result = []
    33. # debug 验证失败的情况
    34. # if not self.multi_num > 0:
    35. # success = False
    36. # thread_q.put((result, success))
    37. # return
    38. sum_num = 1
    39. for i in range(5):
    40. sum_num += i
    41. time.sleep(1)
    42. g_log.info("thread_id<{}> multi_num = {}, output = {}".format(
    43. thread_id, self.multi_num, sum_num))
    44. success = True
    45. result.append(sum_num)
    46. thread_q.put((result, success))
    47. if __name__ == "__main__":
    48. log_file = os.path.join(os.path.abspath(os.path.dirname(__file__)),
    49. "test.log")
    50. log = init_log(log_file)
    51. log.info("multiprocess test")
    52. g_log = log
    53. thread_list = []
    54. thread_q = multiprocessing.Queue()
    55. for i in range(3):
    56. test = PrintNumber(i)
    57. # 重点注意!
    58. p = multiprocessing.Process(target=test.run_task, args=(thread_q,))
    59. p.start()
    60. thread_list.append(p)
    61. log.info("main thread")
    62. test_main = PrintNumber(10)
    63. test_main.run_task(thread_q)
    64. for p in thread_list:
    65. p.join()
    66. log.info("thread join success!")
    67. if not len(thread_list) + 1 == thread_q.qsize():
    68. log.error(
    69. "thread process false! input thread num:{}, output thread num:{}".
    70. format(len(thread_list) + 1, thread_q.qsize()))
    71. sys.exit(-1)
    72. result_list = []
    73. sucess_list = []
    74. for i in range(thread_q.qsize()):
    75. thread_q_temp = thread_q.get()
    76. result_list.extend(thread_q_temp[0])
    77. sucess_list.append(thread_q_temp[1])
    78. for sucess in sucess_list:
    79. if not sucess:
    80. log.error("thread process false! sucess is false!")
    81. sys.exit(-1)
    82. log.info("all thread process success!")

    参考:

    Python logging同时输出到屏幕和文件 - 孤鸿的天空

    Python logging浅尝(将log同时输出到Console和日志文件)_小桔帽的博客-CSDN博客_python日志输出到文件

  • 相关阅读:
    typeScript--[es6class类实现继承]
    Android 性能优化
    【SpringBoot笔记06】SpringBoot集成log4j2日志框架
    【Leetcode】【中等】1726.同积元组
    SAP顾问英语自学的免费且有效的方法汇总!--一文搞定英语学习
    Everything——检索神兵
    docker资源控制
    算法day30
    上交所实时行情文件汇总
    Bevy的一些窗口设置
  • 原文地址:https://blog.csdn.net/mxdsdo09/article/details/125409897
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号