
本文旨在介绍如何使用 Python 的 subprocess 模块并发执行多个子进程,并通过线程池来显著提高程序的执行效率。我们将分析常见的使用 subprocess.Popen 和 .communicate() 方法的场景,并提供使用 ThreadPool 并发等待子进程完成的示例代码。
在使用 subprocess 模块执行多个子进程时,一个常见的误解是 Popen 函数会阻塞程序的执行。实际上,Popen 函数是非阻塞的,它会立即返回一个 Popen 对象,允许程序继续执行。然而,Popen 对象的 communicate() 方法是阻塞的,它会等待子进程执行完毕并返回其输出。如果在循环中依次调用 communicate() 方法,实际上会导致子进程按顺序执行,从而降低程序的效率。
为了解决这个问题,可以使用线程池来并发等待子进程完成。线程池可以创建多个线程,每个线程负责等待一个子进程完成。这样,多个子进程可以同时运行,从而提高程序的执行效率。
下面是一个使用线程池并发等待子进程完成的示例代码:
import subprocess
import logging
from multiprocessing.pool import ThreadPool
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
log = logging.getLogger(__name__)
def runShowCommands(cmdTable) -> dict:
"""return a dictionary of captured output from commands defined in cmdTable."""
procOutput = {} # dict to store the output text from show commands
procHandles = {}
for cmd, command in cmdTable.items():
try:
log.debug(f"running subprocess {cmd} -- {command}")
procHandles[cmd] = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
except Exception as e:
log.error(f"Error launching subprocess {cmd}: {e}")
continue
def handle_proc_stdout(handle):
try:
proc = procHandles[handle]
stdout, stderr = proc.communicate(timeout=180)
procOutput[handle] = stdout.decode("utf-8") # turn stdout portion into text
log.debug(f"subprocess returned {handle}")
if stderr:
log.error(f"subprocess {handle} returned stderr: {stderr.decode('utf-8')}")
except subprocess.TimeoutExpired:
log.error(f"subprocess {handle} timed out")
proc.kill() # Terminate the process
except Exception as e:
log.error(f"Error handling subprocess {handle}: {e}")
threadpool = ThreadPool()
threadpool.map(handle_proc_stdout, procHandles.keys())
threadpool.close()
threadpool.join()
return procOutput
if __name__ == '__main__':
cmdTable = {
'himom': "echo hi there momma",
'goodbye': "echo goodbye",
'date': "date",
'sleep': "sleep 2 && echo slept"
}
output = runShowCommands(cmdTable)
for cmd, out in output.items():
print(f"Output from {cmd}:\n{out}")代码解释:
runShowCommands(cmdTable) 函数:
if __name__ == '__main__': 块:
注意事项:
总结:
通过使用线程池,可以并发执行多个子进程,从而显著提高程序的执行效率。 在处理大量并发任务时,线程池是一种非常有用的技术。 请记住考虑超时处理、错误处理、线程安全性和资源限制等因素,以确保程序的正确性和稳定性。
以上就是使用线程池并发执行子进程以提高效率的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号