Найти - Пользователи
Полная версия: Thread
Начало » Python для новичков » Thread
1
avdoshkin
Есть два scripts, первый выполняется без потока, второй с потоком, но результат по выполнения одинаковый. Поясните, как может быть такое?
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto import rfc1902


def eval_model():
for ln in open('lst'):
errorIndication,errorStatus,errorIndex,varBinds = cmdgen.CommandGenerator().getCmd(cmdgen.CommunityData('None', 'public'),
cmdgen.UdpTransportTarget((ln.split()[0],161),retries=0),(1,3,6,1,4,1,171,12,8,1,1,3,0))

if __name__ == "__main__":
eval_model()

real 1m32.357s
user 1m7.872s
sys 0m2.608s
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto import rfc1902
from Queue import Queue
from threading import Thread

num_threads = 100
queue = Queue()

ips = [line for line in open('lst')]

def pinger(i, q):
while True:
ip = q.get()
cmdgen.CommandGenerator().getCmd(cmdgen.CommunityData('None', 'public'),
cmdgen.UdpTransportTarget((ip.split()[0],161),retries=1),(1,3,6,1,4,1,171,12,8,1,1,3,0))
q.task_done()

for i in range(num_threads):
worker = Thread(target=pinger, args=(i, queue))
worker.setDaemon(True)
worker.start()

for ip in ips:
queue.put(ip.rstrip())
queue.join()

real 1m24.136s
user 1m13.941s
sys 0m11.661s
Андрей Светлов
А почему он должен быть разный?
И почему вы заводите сто потоков? Из соображения “маслом кашу не испортишь”?
avdoshkin
Андрей Светлов
А почему он должен быть разный?
И почему вы заводите сто потоков? Из соображения “маслом кашу не испортишь”?
Мне нужно уменьшить опроса сети, который состоит из 700 узлов, при использовании потока время должно сократиться. Почему взял 100, у меня 700 устройств для опроса, прикинул, взял сто потоков
hr6134
Почитайте вот эту статью на хабре. Скорее всего потоки Вам здесь не помогут.
http://habrahabr.ru/blogs/python/84629/
avdoshkin
немного изменим вместо PySNMP воспользуемся net-snmp и вызовем его через subporcess
результат сразу же меняется.
import subprocess
from Queue import Queue
from threading import Thread

num_threads = 50
queue = Queue()

ips = [line for line in open('lst')]

def pinger(i, q):
while True:
ip = q.get()
subprocess.call('snmpget -v2c -c public {0} 1.3.6.1.4.1.171.12.8.1.1.3.0'.format(ip),
stdout=open('/dev/null','w'),stderr=subprocess.STDOUT,shell=True)
q.task_done()

for i in range(num_threads):
worker = Thread(target=pinger, args=(i, queue))
worker.setDaemon(True)
worker.start()

for ip in ips:
queue.put(ip.rstrip())
queue.join()

real 0m15.126s
user 1m1.816s
sys 0m15.737s
результат без потока:
import subprocess
for ip in open('lst'):
subprocess.call('snmpget -v2c -c public {0} 1.3.6.1.4.1.171.12.8.1.1.3.0'.format(ip.rstrip()),
stdout=open('/dev/null','w'),stderr=subprocess.STDOUT,shell=True)

real 2m10.877s
user 0m35.538s
sys 0m7.292s
Кто еще может объяснить по поводу потоков, а именно по моему случаю?
Андрей Светлов
Это такая pysnmp чудесатая.
Запустите асинхроный диспетчер http://pysnmp.sourceforge.net/docs/4.x/index.html#ASYNCH-ONELINER-APPS
И, кажется, будет вам счастье в одном потоке.
avdoshkin
Андрей Светлов
Это такая pysnmp чудесатая.
Запустите асинхроный диспетчер http://pysnmp.sourceforge.net/docs/4.x/index.html#ASYNCH-ONELINER-APPS
И, кажется, будет вам счастье в одном потоке.
результат с асинхроный диспетчером, хоть и с одном потоком или 10-ми потоками все тоже
from Queue import Queue
from threading import Thread
from pysnmp.entity.rfc3413.oneliner import cmdgen

num_threads = 10
queue = Queue()
ips = [line for line in open('/home/bin/dlink.lst')]

def pinger(i, q):
while True:
ip = q.get()
def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
pass
# print 'sendRequestHandle =', sendRequestHandle
# print 'errorIndication =', errorIndication
# print 'errorStatus =', errorStatus
# print 'varBinds =', varBinds
# print 'cbCtx =', cbCtx

asynCommandGenerator = cmdgen.AsynCommandGenerator()
sendRequestHandle = asynCommandGenerator.asyncNextCmd(cmdgen.CommunityData('None', 'public'),
cmdgen.UdpTransportTarget((ip.split()[0], 161),retries=0),((1,3,6,1,4,1,171,12,8,1,1,3,0),),(cbFun, None))
asynCommandGenerator.snmpEngine.transportDispatcher.runDispatcher()
q.task_done()

for i in range(num_threads):
worker = Thread(target=pinger, args=(i, queue))
worker.setDaemon(True)
worker.start()

for ip in ips:
queue.put(ip.rstrip())
queue.join()

real 1m19.577s
user 1m10.796s
sys 0m11.305s
Есть еще мысли по поводу потока?
Андрей Светлов
Вы меня неправильно поняли. Я имел в виду нечто вроде
from pysnmp.entity.rfc3413.oneliner import cmdgen

ips = [line for line in open('/home/bin/dlink.lst')]

def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
print 'sendRequestHandle =', sendRequestHandle
print 'errorIndication =', errorIndication
print 'errorStatus =', errorStatus
print 'varBinds =', varBinds
print 'cbCtx =', cbCtx

asynCommandGenerator = cmdgen.AsynCommandGenerator()
for ip in ips:
sendRequestHandle = asynCommandGenerator.asyncNextCmd(
cmdgen.CommunityData('None', 'initial_pysnmp'),
cmdgen.UdpTransportTarget((ip.split()[0], 161),retries=0),
((1,3,6,1,4,1,171,12,8,1,1,3,0),),(cbFun, None))

asynCommandGenerator.snmpEngine.transportDispatcher.runDispatcher()
avdoshkin
Андрей Светлов
Вы меня неправильно поняли. Я имел в виду нечто вроде
from pysnmp.entity.rfc3413.oneliner import cmdgen

ips = [line for line in open('/home/bin/dlink.lst')]

def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
print 'sendRequestHandle =', sendRequestHandle
print 'errorIndication =', errorIndication
print 'errorStatus =', errorStatus
print 'varBinds =', varBinds
print 'cbCtx =', cbCtx

asynCommandGenerator = cmdgen.AsynCommandGenerator()
for ip in ips:
sendRequestHandle = asynCommandGenerator.asyncNextCmd(
cmdgen.CommunityData('None', 'initial_pysnmp'),
cmdgen.UdpTransportTarget((ip.split()[0], 161),retries=0),
((1,3,6,1,4,1,171,12,8,1,1,3,0),),(cbFun, None))

asynCommandGenerator.snmpEngine.transportDispatcher.runDispatcher()
Спасибо, за ответ! Проверил но как-то все странно работает, больше 50 устройств не может обработать, в результате получаю списки а в списке кортежи и говорит что “No SNMP response received before timeout”. Как-то всё веселенько получается.
[('a575021578',), ('a575021787',), ('a575021885',), ('a575021573',), ('a575021569',), ('a575022013',), ('a575022090',), ('a575021775',), ('a575022030',), ('a575022247',), ('a575021748',), ('a575021907',), ('a575022076',), ('a575021672',), ('a575021657',), ('a575022173',), ('a575022148',), ('a575021852',), ('a575021705',), ('a575021973',), ('a575022285',), ('a575021946',), ('a575021688',), ('a575022158',), ('a575022098',)]

sendRequestHandle = 193244589
errorIndication = No SNMP response received before timeout
errorStatus = 0
varBinds = ()
cbCtx = None
Если опросить 50 устройств через асинхроный диспетчер то все ок, если больше то вывод описал выше. Есть у вас доводы?
Питонер
Возможно обработка 50-сяти snmp запросов занимает более времени таймаута запроса, в рез-те часть ответов отбрасывается. Попробуйте увеличить таймаут ожидания ответа в pysnmp.

Что касается причин неудачи с МТ подходом - возможно проблема в GIL в сочетании с большими затратами на вычисления внутри pysnmp.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB