假设我有以下ip范围" 10.0.0.x"。我需要循环这个范围的ips - " 10.0.0.1-255",ping每个,并检查响应。
这是我的代码:
for ip in range(1, 256):
fullIP = '10.0.0' + ip
if(Ping(fullIP) == True):
print(fullIP + ' responded')
else:
print(fullIP + ' did not respond')
此代码有效,但不幸的是它很慢 我想通过多线程提高效率,所以我做了以下几点:
def PingRange(start, end):
for ip in range(start, end):
fullIP = '10.0.0' + ip
if(Ping(fullIP) == True):
print(fullIP + ' responded')
else:
print(fullIP + ' did not respond')
try:
thread.start_new_thread( PingRange, (1, 123))
thread.start_new_thread( PingRange, (123, 256))
except:
print "Error: unable to start thread"
此代码也有效,但它可以更好,更通用 如果这段代码写得正确,那么我就不会经常创建两个线程;我会创建尽可能多的线程,因为操作系统会允许我 有些计算机允许8个线程,有些只允许4个,有些甚至不允许线程。
如何让这个程序使用Python中最大的线程数?
答案 0 :(得分:4)
此问题非常适合使用线程池。线程池以恒定数量的线程运行,获取工作项(函数或方法),并在其线程池中执行这些工作项。它具有内置排队功能,因此如果您将一百个工作项提供给五个线程的池,它将执行所有一百个项目,但不会同时运行超过五个项目。
Python中有两个内置线程池选项(取决于您使用的版本) - multiprocessing.dummy.Pool
和concurrent.futures.ThreadPoolExecutor
。 ThreadPoolExecutor
仅在Python 3.x中内置,但PyPI提供了一个backport。 multiprocessing.dummy.Pool
可在2.6+中使用。使用multiprocessing.dummy.Pool
,您的代码就变得如此简单:
import multiprocessing.dummy
def ping_range(start, end):
num_threads = # Number of threads to run in the pool.
p = multiprocessing.dummy.Pool(num_threads)
p.map(ping, [10.0.0.x for x in range(start,end)])
if __name__ == "__main__":
PingRange(0, 255)
下一个问题是num_threads
的用途。对于拥有最大允许线程数的系统,我认为你略有错误信息。您可以在任何系统上创建任意数量的Thread
个对象,并且实际上什么都不会阻止您,但在某个时刻您将创建如此多的线程,系统将无法处理它和性能将开始更糟,而不是更好。
CPU绑定应用程序的经验法则(意味着它主要要求CPU完成工作)是运行与CPU一样多的线程。但是,此ping操作受I / O限制,这意味着大多数工作是将ping请求发送到外部系统,然后等待响应,这不需要CPU执行任何操作。在这些情况下,通常可以使用超过CPU的数量。我们可以保守并使用2 * number_of_cpus
,但您可以尝试使用更大的数字。
import multiprocessing
num_threads = 2 * multiprocessing.cpu_count()
全部放在一起:
import multiprocessing.dummy
import multiprocessing
def ping(ip):
success = # Run the ping command here
if success:
print("{} responded".format(ip))
else:
print("{} did not respond".format(ip))
return success
def ping_range(start, end):
num_threads = 2 * multiprocessing.cpu_count()
p = multiprocessing.dummy.Pool(num_threads)
p.map(ping, [10.0.0.x for x in range(start,end)])
if __name__ == "__main__":
ping_range(0, 255)