user857990
user857990

Reputation: 1220

Speed up Python script's for loop

Assuming you got something like this (copied from here):

#!/usr/bin/python
from scapy.all import *

TIMEOUT = 2
conf.verb = 0
for ip in range(0, 256):
    packet = IP(dst="192.168.0." + str(ip), ttl=20)/ICMP()
    reply = sr1(packet, timeout=TIMEOUT)
    if not (reply is None):
         print reply.src, "is online"
    else:
         print "Timeout waiting for %s" % packet[IP].src

There is no need to wait for each ping to finish before trying the next host. Could I put the loop interior each time into the background along the lines of the & in:

for ip in 192.168.0.{0..255}; do 
ping -c 1 $ip &
done

Upvotes: 2

Views: 851

Answers (2)

btel
btel

Reputation: 5693

You can use threading or multiprocessing module to run aynchronous/non-blocking IO calls.

Read about hte difference on SO:

multiprocess or threading in python?

Upvotes: 0

Jordan
Jordan

Reputation: 32522

The first thing you should do is change your range to range(0, 256) so that it is inclusive of 0-255.

Second, you're looking at Python's threading, which can be somewhat similar to Bash process daemonization at an abstract level.

Import multiprocessing and create a pool:

from multiprocessing.pool import ThreadPool
pool = ThreadPool(20)  # However many you wish to run in parallel

So take the ping lookup, which is everything inside of the for loop, and make it a function.

def ping(ip):
    packet = IP(dst="192.168.0." + str(ip), ttl=20)/ICMP()
    reply = sr1(packet, timeout=TIMEOUT)
    if not (reply is None):
         print reply.src, "is online"
    else:
         print "Timeout waiting for %s" % packet[IP].src

Then in your for loop,

for ip in range(0, 256):
    pool.apply_async(ping, (ip,))

pool.close()
pool.join()

pool.join() is what waits for all of your threads to return.

Upvotes: 5

Related Questions