Python Forum

Full Version: Appending a list in a class from a callback function
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi all,
This is my first post. Usually I can search out answers to my problems but today I'm having a bit of difficulty finding what I'm doing wrong populating a list of MAC addresses from a callback function, all enclosed within a class. The list is always empty on the very last line where I print it out. If I print the contents of the list from within the callback function each time it is raised, it looks correct. I'm having a feeling it has to do with scope or might need a lambda function but I'm foggy on some aspects there. I apologize for my numerous un-pythonic statements. I'm totally self taught and come from using mainly Visual Basic so I can be a bit of a sloppy coder at times. Here's my code: NOTE: This is normally executed on a Raspberry Pi.

import nmap, sys, socket, subprocess

class IP_Roam():
    def __init__(self, root_ip="", display_on=False):
        self.mac_list = []
        self.display_on = display_on
        self.router_ip = root_ip
        self.end_ip = ""

    def callback_result(self, host, scan_result):
        if self.display_on:
            sys.stdout.write('\rScanning ' + str(host).ljust(15, ' '))
            sys.stdout.flush()

        for ip in scan_result['scan']:

            try:
                mac = scan_result['scan'][u'' + str(ip)]['addresses'][u'mac']
                if mac:
                    myscan.mac_list.append(mac)
                #ipv4 = scan_result['scan'][u'' + str(ip)]['addresses'][u'ipv4']
            except:
                # This happens when it finds itself
                pass

    def go(self):
        if self.router_ip == "":
            self.who_am_i()
        nma = nmap.PortScannerAsync()
        nma.scan(self.router_ip + "/24", arguments='-sP', callback=self.callback_result)

        while nma.still_scanning():
            nma.wait(2)

        if self.display_on:
            for mac in self.mac_list:
                print(mac)

    def who_am_i(self, ipend=None):
        my_ips = subprocess.check_output(("hostname", "-I"), stderr=None).decode('utf-8').split(" ")
        nodes = my_ips[0].split(".")
        self.router_ip = str(nodes[0]) + "." + str(nodes[1]) + ".1.0"

        if ipend is not None:
            self.end_ip = str(nodes[0]) + "." + str(nodes[1]) + ".1." + str(ipend)
            if self.display_on:
                print("Using: " + self.router_ip + "-" + self.end_ip)
        else:
            if self.display_on:
                print("Using: " + self.router_ip)

if __name__ == "__main__":
    myscan = IP_Roam(display_on=True)
    myscan.go()
    print(myscan.mac_list)
Does
myscan.mac_list.append(mac)
need to be
self.mac_list.append(mac)
Think
Actually, I originally had it that way with the same result. I changed it in hopes that it'd resolve the issue.
I just changed it back to
self.mac_list.append(mac)
with no change. mac_list is still not populated when IP_Roam.go() completes.
Having a try/except that excepts every exception and pass when there is an exception, will silently let any exception go by.
I've simplified my question a bit here to see if anyone can help me with this. When I run the following IP Scan, the results print fine from within the callback function. The whole list will even appear if I do a print() of self.mac_list from within the callback function. However, when the routine terminates and go() returns self.mac_list it is always empty. Anyone know what I am missing here?

Thanks,
Jim
import nmap

class IP_Roam():
    def __init__(self, root_ip="", display_on=False):
        self.mac_list = []

    def callback_result(host, scan_result):
        print(scan_result)
        self.mac_list.append(scan_result)

    def go():
        nma = nmap.PortScannerAsync()
        nma.scan(hosts='192.168.1.0/30', arguments='-sP', callback=callback_result)

        while nma.still_scanning():
            print("Waiting >>>")
            nma.wait(2)   # you can do whatever you want but I choose to wait after the end of the scan
        return self.mac_list


if __name__ == "__main__":
    ps = IP_Roam()
    results = ps.go()
    print(results)