Python Threading 和 Telnet 意外结果

问题描述

我编写了一个脚本,可以通过 telnet 连接到某些网络设备并提取清单并将其放入一个文件中。我使用线程来加速脚本,因为我有大约 160 个节点。我编写了一个 telnet 到每个节点的函数,检索库存,将输出写入文件,然后断开会话。当我在单个函数下执行这三个步骤时,脚本运行良好。但是,我决定创建一个类并将这三个步骤分解为不同的方法。现在,当我运行脚本时,它只从列表中的第一个节点检索数据。我需要一些帮助来弄清楚为什么脚本不起作用。

import concurrent.futures
import time
import telnetlib
from myFunctions import get_node_list_TA5K

class Ta5kTelnet:

    def __init__(self):
        self.tn = telnetlib.Telnet()

    def connect(self,hostname,username,password):
        self.tn.open(hostname,23,5)
        self.tn.read_until(b'Username:',5)
        self.tn.write(username.encode('ascii') + b'\n')
        self.tn.read_until(b'Password:',5)
        self.tn.write(password.encode('ascii') + b'\n')
        if b'>' in self.tn.read_until(b'>',5):
            self.tn.write(b'en\n')
            self.tn.read_until(b'#',5)
            self.tn.write(b'term len 0\n')
            output = self.tn.read_until(b'#',5)
            return output
        else:
            print(f'{hostname} is spare shelf')

    def send(self,command,waitfor):
        self.tn.write(command + b'\n')
        result = self.tn.read_until(waitfor,180).decode()
        return result
    
    def disconnect(self):
        self.tn.close()


tlnt = Ta5kTelnet()


def inventory(node_names):
    tlnt.connect(node_names,'username','password')
    shelf_inventory = tlnt.send(b'show system inventory',b'#')
    tlnt.disconnect()
    with open(f'{node_names}_inventory.txt','a') as f:
        f.write(shelf_inventory)



#adtran_nodes = get_node_list_TA5K()
adtran_nodes = ['BXR1-NODE1-COT1','BXR6-NODE1-COT6']


start = time.perf_counter()

with concurrent.futures.ThreadPoolExecutor() as executor:
    results = executor.map(inventory,adtran_nodes)



print(time.perf_counter() - start)

解决方法

您在两个线程之间共享一个 telnet 连接,并且没有锁定或同步。

无法知道连接、登录、发送、read_until 序列将按哪个顺序运行。

每个线程都需要自己的连接对象。

此外,我会重构从 telnetlib.Telnet 派生的事物,并且在此过程中,为了确保连接始终正确关闭,请使用 __enter__ 和 {{ 使其成为上下文管理器1}}:

__exit__