Потоки Python с web.py и pysnmp для создания веб-службы

Я пытаюсь создать небольшую службу для своей домашней сети, которая считывает значения SNMP с моего коммутатора для порта, на котором работает маршрутизатор, выполняет несколько вычислений и возвращает текущее среднее использование пропускной способности.

Я заставил pysnmp работать достаточно хорошо, считывая значения snmp каждые две секунды... затем я решил интегрировать web.py, чтобы создать очень простой веб-сервис, который возвращает JSON средней загрузки и загрузки в килобитах.

Для этого я должен использовать многопоточность, чтобы поддерживать опрос SNMP в фоновом режиме. Однако я NOOOB, и он работает неправильно - когда я загружаю значение в свой браузер, кажется, что по какой-то причине создается второй поток процесса SNMP, я не могу понять, почему.

Вот код:

from pysnmp.entity.rfc3413.oneliner import cmdgen
from time import sleep
import threading
import json
import web

LOCK = threading.Lock()

class getBW(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.data = dict(upload="0",download="0",)
        self.lock = LOCK
        self.start()

    def run(self):

        router_ip = "192.168.2.2"
        snmp_community = "public"
        upload_mib = "1.3.6.1.2.1.2.2.1.16.1"
        download_mib = "1.3.6.1.2.1.2.2.1.10.1"
        read_interval = 2
        up_octets = 0
        dn_octets = 0
        last_up_octets = 0
        last_dn_octets = 0
        up_change = 0
        dn_change = 0
        avg_up =0
        avg_dn =0
        up_hist = [0,0,0,0,0] 
        dn_hist = [0,0,0,0,0]
        i = 0
        cmdGen = cmdgen.CommandGenerator()

        while (1):
            errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
                cmdgen.CommunityData(snmp_community),
                cmdgen.UdpTransportTarget((router_ip, 161)),
                upload_mib,
                download_mib
            )

            # Check for errors and print out results
            if errorIndication:
                print(errorIndication)
            else:
                if errorStatus:
                    print('%s at %s' % (
                        errorStatus.prettyPrint(),
                        errorIndex and varBinds[int(errorIndex)-1] or '?'
                        )
                    )
                else:
                    for name, val in varBinds:
                        if str(name) == upload_mib:
                            if up_octets > 0: 
                                last_up_octets = up_octets
                                up_change = val-last_up_octets
                                # convert to kilobits/s
                                up_change = (((up_change*8)/1000)/read_interval)
                                up_hist[i] = up_change
                                avg_up=(sum(up_hist)/len(up_hist))
                            up_octets = val
                            #print ('%d kilobit per second upload, %d average' % (up_change,avg_up))

                        elif str(name) == download_mib:
                            if dn_octets > 0:
                                last_dn_octets = dn_octets
                                dn_change = val-last_dn_octets
                                # convert to kilobits/s
                                dn_change = (((dn_change*8)/1000)/read_interval)
                                dn_hist[i] = dn_change
                                avg_dn=(sum(dn_hist)/len(dn_hist))
                                i += 1
                                i = i % 5 # if I is 5 reset to 0
                            dn_octets = val
                            #print ('%d kilobit per second download, %d average' % (dn_change,avg_dn))

            #output values to dict
            self.lock.acquire()
            self.data = dict(upload=str(avg_up),download=str(avg_dn),)
            self.lock.release()
            print("UPLOAD: %d change, %d average; DOWNLOAD: %d change, %d average" % (up_change,avg_up,dn_change,avg_dn))
            print("sleeping for %i secs...\r\n" % read_interval)
            sleep(read_interval)

try:
    BW = getBW()
except:
    print "Error: unable to start thread"

urls = ("/.*", "hello")
app = web.application(urls, globals())

class hello:
    def __init__(self):
        self.lock = LOCK
    def GET(self):
        self.lock.acquire()
        thedata = BW.data
        self.lock.release()
        return json.dumps(thedata)

if __name__ == "__main__":
    #start web service
    app.run()

Я был бы ОЧЕНЬ признателен за вашу помощь. Пожалуйста, помните, что я полный ноль в тредах и только изучаю Python. Спасибо!


person Blark    schedule 20.11.2012    source источник


Ответы (1)


Вы используете встроенный веб-сервер web.py. По умолчанию он включает «перезагрузку модуля», и перезагрузка дважды загружает основной модуль. Поскольку вы начинаете свой поток во время импорта, вы запускаете два потока.

Простое исправление будет состоять в том, чтобы переместить создание потока в блок __main__, чтобы он создавался только один раз:

if __name__ == "__main__":
    BW = getBW()
    #start web service
    app.run()
person barracel    schedule 20.11.2012