The docs are here.
Callable classes
When you instantiate a Thread, you give it a function to run, or something else callable.
If you want to pass parameters, one way is to make a callable class. While Thread does
allow you to pass parameters, the callable class pattern is useful in instances where you
do not have this facility. So you pass the parameters to the constructor, and implement
the __call__() method.
class TryHost:
def __init__(self,addr):
self.addr = addr
def __call__(self):
addr = self.addr
...
Examples
Mass Ping
A simple command to see which hosts are up on a subnet. This is intended for /24 subnets like 192.168.0.0.
The basic idea is that ping -w1 -c1 192.168.4.23 will include bytes from in its output if it gets a response. On a LAN we don't need more than a second to get a reply if a host is up, and we don't need to send more than one ping. To make this a quick process, we run all 200+ pings in parallel. So the whole thing takes a couple of seconds.
#!/usr/bin/env python3
from subprocess import run, PIPE
from threading import Thread
import os
import sys
import re
#ping -w1 -c1 "192.168.$localnet.$s" # 2>&1 >| "$s"
# if a host is up, the string "bytes from" will be in the stdout
hosts_up = set()
class TryHost:
def __init__(self,addr):
self.addr = addr
def __call__(self):
addr = self.addr
cmd = ["ping","-w1","-c1",addr]
m = run(cmd,stdout=PIPE,stderr=PIPE)
a = m.stdout.decode()
if "bytes from" in a:
hosts_up.add(addr)
def helpexit(n=1):
print(f"{sys.argv[0]} <subnet number>")
exit(n)
def main():
args = sys.argv[1:]
try:
if len(args) > 0:
arg = args[0]
if "." in arg:
xs = arg.split(".") + "0.0.0.0".split(".")
xs = xs[:3]
else:
xs = ["192","168",args[0]]
else:
m = run(["ip","-4","addr"],stdout=PIPE,stderr=PIPE)
a = m.stdout.decode().splitlines()
b = [ x for x in a if "192.168" in x ]
d = []
for x in b:
m = re.search(r"192\.168\.(\d+)\.(\d+)",x)
if m:
d.append(m.group(1))
if len(d) == 0:
print(f"Can't autodetect subnet (ip -4 addr returned nothing of use)")
exit(1)
if len(d) > 1:
print(f"More than one subnet found: {', '.join(d)}")
exit(1)
xs = ["192","168",d[0]]
except Exception:
helpexit()
threads = []
for x in range(2,253):
addr = ".".join(xs+[str(x)])
thread = Thread(target=TryHost(addr))
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
for addr in sorted(hosts_up,key=lambda t: int(t.split(".")[-1])):
print(addr)
if __name__ == "__main__":
main()