在Python脚本中同时使用多处理和多线程来加快执行速度



我有以下子网范围:10.106.44.0/24-10.106.71.0/24。我正在编写一个Python脚本来ping所有子网中的每个IP。为了加快这个脚本的速度,我尝试同时使用多处理和多线程。我正在为每个子网创建一个新进程,并创建一个线程来ping该子网中的每个主机。我想问两个问题:

  1. 这是解决这个问题的最佳方法吗
  2. 如果是,我将如何实施这一点

我会首先尝试使用线程。你可以尝试创建一个线程池,其大小是你必须执行的ping的总数,但最终我相信这不会比使用与你拥有的CPU核心数量相等的线程池大小好多少(解释如下(。以下是使用线程和多处理的两种方法的比较:

线程池执行器(255个线程(

from concurrent.futures import ThreadPoolExecutor
import os
import platform
import subprocess
import time
def ping_ip(ip_address):
param = '-n' if platform.system().lower() == 'windows' else '-c'
try:
output = subprocess.check_output(f"ping {param} 1 {ip_address}", shell=True, universal_newlines=True)
if 'unreachable' in output:
return False
else:
return True
except Exception:
return False

def main():
t1 = time.time()
ip_addresses = ['192.168.1.154'] * 255
#with ThreadPoolExecutor(os.cpu_count())) as executor: # uses number of CPU cores
with ThreadPoolExecutor(len(ip_addresses)) as executor:
results = list(executor.map(ping_ip, ip_addresses))
#print(results)
print(time.time() - t1)
if __name__ == '__main__':
main()

打印:

2.049474000930786

您可以尝试使用更少的线程(ThreadPoolExecutor构造函数的max_workers参数(。参见:concurrent.futures

我发现运行8个线程(我拥有的内核数量(也差不多(时间:2.2745485305786133(。我认为原因是,尽管ping是一项与I/O相关的任务,但对子进程的调用必须在内部创建一个使用相当多CPU的新进程,因此并发性在一定程度上受到处理器的限制

ProcessPoolExecutor(8核(

from concurrent.futures import ProcessPoolExecutor
import os
import platform
import subprocess
import time
def ping_ip(ip_address):
param = '-n' if platform.system().lower() == 'windows' else '-c'
try:
output = subprocess.check_output(f"ping {param} 1 {ip_address}", shell=True, universal_newlines=True)
if 'unreachable' in output:
return False
else:
return True
except Exception:
return False

def main():
t1 = time.time()
ip_addresses = ['192.168.1.154'] * 255
with ProcessPoolExecutor() as executor:
results = list(executor.map(ping_ip, ip_addresses))
#print(results)
print(time.time() - t1)
if __name__ == '__main__':
main()

打印:

2.509838819503784

请注意,在我的Linux系统上,您必须是超级用户才能发出ping命令

最新更新