I want a quick way to check if a computer on the LAN is awake or not given its IP address (on Windows) without waking it up. I wrote the following, which works:
def is_awake(ipOrName, timeout=0.05):
try:
tt = round(timeout*1000)
cmdargs = ["ping", "-n", "1", "-w", f'{tt}', "-a", ipOrName]
result = subprocess.run(cmdargs, capture_output=True, text=True)
if "Received = 1" in result.stdout:
return True
else:
return False
except Exception as e:
print(f"Error checking IP reachability: {e}")
return False
But I noticed that this could be quite slow when running it to sequentially check a lot of IP addresses (30, for example). I can add print statements to the code and see a visible delay before and after the subprocess.run() line for the computers that are turned off (it's essentially instant for the IPs corresponding to computers that are turned on). It almost seems like the timeout parameter isn't being respected, or maybe there's some other reason the subprocess.run() function is taking so long to return. I'm not sure.
Is there any better way to do this? The following is much faster, but I can't use it because it wakes the computer from sleep:
def is_reachable(ipOrName, port = 445, timeout=0.05):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(timeout)
try:
s.connect((ipOrName, int(port)))
s.shutdown(socket.SHUT_RDWR)
return True
except:
return False
finally:
s.close()
Any ideas?
This video demonstrates how slow my first method is: https://www.youtube.com/shorts/SZSMOucKiuQ
The video shows that a single failed ping completes in about the expected time, but since each ping is done serially, the aggregate time is relatively long. "Relatively" because this is perfectly acceptable in many situations.
You could parallelize these pings. Your current function only handles a single ping, so I had to make up another function that processes many. In the first case, you could use a thread pool
But since ping.exe is a separate process already, you could use
Popeninstead ofrun, which doesn't wait for one ping to complete before starting the next.As a side note, a single ping with a short timeout will sometimes give you false negatives. Several pings with at a least a few second timeout would catch more. If running in parallel speeds things up enough, you may consider more attempts.