无法使用 python 并行化(线程)telnet 连接
cannot parallelize (threads) telnet connections with python
我有一个代码可以连接到多个路由器,使用 telentlib,在其中运行一些代码,最后将输出写入文件。运行流畅
但是,当我不得不访问大量路由器 (+50) 时,任务会消耗大量时间(代码连续运行,一次一个路由器)。然后我想到了实现线程以加速这个过程。
这就是大部分代码(只是其中的一小段):
# We import the expect library for python
import telnetlib
import sys
import csv
import time
import threading
# --- Timers
TimeLogin = 10
TelnetWriteTimeout = 1
TelnetReadTimeout = 2
# --- CSV
FileCsv = "/home/lucas/Documents/script/file.csv"
# --- Extras
cr="\n"
# variables
IP = "A.B.C.D"
User = ["user","password"]
CliLogin = "telnet " + IP
Prompt = ["root@host.*]#"]
PromptLogin = ["login:"]
PromptLogout = ["logout"]
PromptPass = ["Password:"]
CliLine = "ls -l"
class MiThread(threading.Thread):
def __init__(self,num,datos):
threading.Thread.__init__(self)
self.num = num
self.datos = datos
self.systemIP = self.datos[0]
self.tn = telnetlib.Telnet(IP)
self.tn.timeout = TimeLogin
# File declaration
self.FileOutGen = self.systemIP + "_commands"
self.FileOutSend = self.systemIP + "_output"
self.FileOutRx = self.systemIP + "_rx"
self.fg = open(self.FileOutGen,"w")
self.fr = open(self.FileOutRx,"a")
self.fs = open(self.FileOutSend,"w")
def run(self):
print "Soy el hilo", self.num
self.telnetLogin()
self.runLs()
self.telnetLogout()
def telnetLogin(self):
i=self.tn.expect(PromptLogin)
print i
if i:
writeTelnet(User[0],TelnetWriteTimeout)
j=self.tn.expect(PromptPass)
print j
if j:
writeTelnet(User[1],TelnetWriteTimeout)
def telnetLogout(self):
i=self.tn.expect(Prompt)
if i:
writeTelnet("exit",TelnetWriteTimeout)
j=self.tn.expect(PromptLogout)
if j:
print "Logged out OK from SAM"
def runLs(self):
writeLog("Prueba de Ls " + self.systemIP)
self.writeCsv(self.systemIP,1)
i=self.tn.expect(Prompt,TimeLogin)
print i
if i:
# Prompt
CliLine = "ls -l "
writeTelnet(CliLine,TelnetWriteTimeout)
def writeCsv(self,inText,lastIn):
lock.acquire(1)
if lastIn==0:
fc.write(inText + ",")
elif lastIn==1:
fc.write(inText + "\n")
lock.release()
def writeTelnet(inText, timer):
tn.write(inText + cr)
time.sleep(timer)
def writeLog(inText):
print (inText)
t.fs.write("\n" + inText)
def printConsole(inText):
print (inText)
oFile = csv.reader(open(FileCsv,"r"), delimiter=",", quotechar="|")
lock = threading.Lock()
routers = list(oFile)
threads_list = []
for i in range(len(routers)):
FileOutCsv = "00_log.csv"
# creating output file
fc = open(FileOutCsv,"a")
# running routine
t = MiThread(i,routers[i])
threads_list.append(t)
t.start()
...一切都运行良好,但没有时间获得,因为 t.join() 将强制一个线程在运行下一个线程之前完成!
序列化线程的事实(意思是,使用 t.join())让我认为一些内存空间正在共享,因为当我确实想要并行化它们时会出现问题(注释掉 t.join()).
我做错了什么吗?如果需要,我可以提供更多信息,但我真的不知道到目前为止我做错了什么......
根据以往的经验,你需要启动所有线程,并在它们全部启动后让它们加入。
thread_list = []
for i in range(routers):
t = MiThread(i, routers[i])
threadlist.append(t)
t.start()
for i in thread_list:
i.join()
这将启动每个线程,然后等待所有线程完成后再继续。
所以经过一番挖掘,发现了错误。
之前,函数 writeTelnet() 是在 class 之外声明的。一旦移入其中并被其余部分正确引用(即:self.writeTelnet()),一切都按预期工作。
这是新代码的片段:
class MiThread(threading.Thread):
def __init__(self,num,datos):
threading.Thread.__init__(self)
self.num = num
self.datos = datos
self.systemIP = self.datos[0]
self.tn = telnetlib.Telnet(IP)
self.tn.timeout = TimeLogin
# File declaration
self.FileOutGen = self.systemIP + "_commands"
self.FileOutSend = self.systemIP + "_output"
self.FileOutRx = self.systemIP + "_rx"
self.fg = open(self.FileOutGen,"w")
self.fr = open(self.FileOutRx,"a")
self.fs = open(self.FileOutSend,"w")
[ . . . ]
def writeTelnet(self,inText, timer):
self.tn.write(inText + ch_cr)
time.sleep(timer)
oFile = csv.reader(open(FileCsv,"r"), delimiter=",", quotechar="|")
routers = list(oFile)
for i in range(len(routers)):
# creating output file
fc = open(FileOutCsv,"a")
# running routine
t = MiThread(i,routers[i])
t.start()
现在很清楚(至少对我而言):由于不同的线程需要在某个时候写入它们的 telnet 连接,因此它们需要明确地识别它。我发现这样做的唯一方法是将函数包含在 class.
谢谢大家,
卢卡斯
我想你可以把它们聚在一起。像下面这样的东西。 (没试过)
count=20
start=1
for i in range(len(routers)):
if start == count :
for _myth in range(1,i+1):
thread_list[_myth].join()
start+=1
FileOutCsv = "00_log.csv"
# creating output file
fc = open(FileOutCsv,"a")
# running routine
t = MiThread(i,routers[i])
threads_list.append(t)
t.start()
start+=1
我有一个代码可以连接到多个路由器,使用 telentlib,在其中运行一些代码,最后将输出写入文件。运行流畅
但是,当我不得不访问大量路由器 (+50) 时,任务会消耗大量时间(代码连续运行,一次一个路由器)。然后我想到了实现线程以加速这个过程。
这就是大部分代码(只是其中的一小段):
# We import the expect library for python
import telnetlib
import sys
import csv
import time
import threading
# --- Timers
TimeLogin = 10
TelnetWriteTimeout = 1
TelnetReadTimeout = 2
# --- CSV
FileCsv = "/home/lucas/Documents/script/file.csv"
# --- Extras
cr="\n"
# variables
IP = "A.B.C.D"
User = ["user","password"]
CliLogin = "telnet " + IP
Prompt = ["root@host.*]#"]
PromptLogin = ["login:"]
PromptLogout = ["logout"]
PromptPass = ["Password:"]
CliLine = "ls -l"
class MiThread(threading.Thread):
def __init__(self,num,datos):
threading.Thread.__init__(self)
self.num = num
self.datos = datos
self.systemIP = self.datos[0]
self.tn = telnetlib.Telnet(IP)
self.tn.timeout = TimeLogin
# File declaration
self.FileOutGen = self.systemIP + "_commands"
self.FileOutSend = self.systemIP + "_output"
self.FileOutRx = self.systemIP + "_rx"
self.fg = open(self.FileOutGen,"w")
self.fr = open(self.FileOutRx,"a")
self.fs = open(self.FileOutSend,"w")
def run(self):
print "Soy el hilo", self.num
self.telnetLogin()
self.runLs()
self.telnetLogout()
def telnetLogin(self):
i=self.tn.expect(PromptLogin)
print i
if i:
writeTelnet(User[0],TelnetWriteTimeout)
j=self.tn.expect(PromptPass)
print j
if j:
writeTelnet(User[1],TelnetWriteTimeout)
def telnetLogout(self):
i=self.tn.expect(Prompt)
if i:
writeTelnet("exit",TelnetWriteTimeout)
j=self.tn.expect(PromptLogout)
if j:
print "Logged out OK from SAM"
def runLs(self):
writeLog("Prueba de Ls " + self.systemIP)
self.writeCsv(self.systemIP,1)
i=self.tn.expect(Prompt,TimeLogin)
print i
if i:
# Prompt
CliLine = "ls -l "
writeTelnet(CliLine,TelnetWriteTimeout)
def writeCsv(self,inText,lastIn):
lock.acquire(1)
if lastIn==0:
fc.write(inText + ",")
elif lastIn==1:
fc.write(inText + "\n")
lock.release()
def writeTelnet(inText, timer):
tn.write(inText + cr)
time.sleep(timer)
def writeLog(inText):
print (inText)
t.fs.write("\n" + inText)
def printConsole(inText):
print (inText)
oFile = csv.reader(open(FileCsv,"r"), delimiter=",", quotechar="|")
lock = threading.Lock()
routers = list(oFile)
threads_list = []
for i in range(len(routers)):
FileOutCsv = "00_log.csv"
# creating output file
fc = open(FileOutCsv,"a")
# running routine
t = MiThread(i,routers[i])
threads_list.append(t)
t.start()
...一切都运行良好,但没有时间获得,因为 t.join() 将强制一个线程在运行下一个线程之前完成!
序列化线程的事实(意思是,使用 t.join())让我认为一些内存空间正在共享,因为当我确实想要并行化它们时会出现问题(注释掉 t.join()).
我做错了什么吗?如果需要,我可以提供更多信息,但我真的不知道到目前为止我做错了什么......
根据以往的经验,你需要启动所有线程,并在它们全部启动后让它们加入。
thread_list = []
for i in range(routers):
t = MiThread(i, routers[i])
threadlist.append(t)
t.start()
for i in thread_list:
i.join()
这将启动每个线程,然后等待所有线程完成后再继续。
所以经过一番挖掘,发现了错误。
之前,函数 writeTelnet() 是在 class 之外声明的。一旦移入其中并被其余部分正确引用(即:self.writeTelnet()),一切都按预期工作。
这是新代码的片段:
class MiThread(threading.Thread):
def __init__(self,num,datos):
threading.Thread.__init__(self)
self.num = num
self.datos = datos
self.systemIP = self.datos[0]
self.tn = telnetlib.Telnet(IP)
self.tn.timeout = TimeLogin
# File declaration
self.FileOutGen = self.systemIP + "_commands"
self.FileOutSend = self.systemIP + "_output"
self.FileOutRx = self.systemIP + "_rx"
self.fg = open(self.FileOutGen,"w")
self.fr = open(self.FileOutRx,"a")
self.fs = open(self.FileOutSend,"w")
[ . . . ]
def writeTelnet(self,inText, timer):
self.tn.write(inText + ch_cr)
time.sleep(timer)
oFile = csv.reader(open(FileCsv,"r"), delimiter=",", quotechar="|")
routers = list(oFile)
for i in range(len(routers)):
# creating output file
fc = open(FileOutCsv,"a")
# running routine
t = MiThread(i,routers[i])
t.start()
现在很清楚(至少对我而言):由于不同的线程需要在某个时候写入它们的 telnet 连接,因此它们需要明确地识别它。我发现这样做的唯一方法是将函数包含在 class.
谢谢大家,
卢卡斯
我想你可以把它们聚在一起。像下面这样的东西。 (没试过)
count=20
start=1
for i in range(len(routers)):
if start == count :
for _myth in range(1,i+1):
thread_list[_myth].join()
start+=1
FileOutCsv = "00_log.csv"
# creating output file
fc = open(FileOutCsv,"a")
# running routine
t = MiThread(i,routers[i])
threads_list.append(t)
t.start()
start+=1