concurrent.futures.ProcessPoolExecutor() map 无法读取全局变量

concurrent.futures.ProcessPoolExecutor() map can't read global variable

下面是使用 netmiko 进行网络自动化的简单代码: 所以首先我有:

  1. 函数cisco_command 用于从输入文件读取命令
  2. 函数cisco_host从输入文件中读取主机信息
  3. 用于启动与设备的连接的功能open_connection
  4. 多处理函数run_program
  5. 函数main为主程序

所以我的代码有问题,你可以在 open_connection func 上看到我们有全局变量 commands_info 但是如果我们 运行 这个程序通过多处理(run_program func) open_connection func.

无法读取全局变量
import time
import os
import concurrent.futures
from netmiko import ConnectHandler
from functools import partial


full_path = os.path.dirname(__file__)
host_file = os.path.join(full_path, "lab-router.txt")
command_file = os.path.join(full_path, "cisco-log.txt")
starting_time = ""


command_info = []

def cisco_command():
    global command_info
    command_info = []
    with open(command_file, 'r') as commands:
        for line in commands:
            com = line.strip()
            command_info.append(com)
    return command_info
    
def cisco_host():
    global starting_time
    hosts_info = []
    with open(host_file, 'r') as devices:
        for line in devices:
            deviceip = line.strip()
            host = {
                'device_type': 'cisco_ios',
                'ip': deviceip,
                'username': 'dodo',
                'password': 'dodo',
                'secret': 'dodo'
            }
            hosts_info.append(host)

    starting_time = time.perf_counter()
    return hosts_info

def open_connection(host):
    global command_info
    sendcommand = ""     
    try:
        connection = ConnectHandler(**host)
        print('Connection Established to Host:', host['ip'])
        connection.enable()
        for i in command_info:
            sendcommand += "\n"
            sendcommand += "==== {} ====".format(i)
            sendcommand += "\n"
            sendcommand += connection.send_command(i)
            sendcommand += "\n"
# return sendcommand
        with open("{}/{}_log.txt".format(full_path, host['ip']), 'w') as nf:
            nf.write(sendcommand)  
    except:
        print('Connection Failed to host', host['ip'])
    

        
def run_program(hosts_info):
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = executor.map(open_connection, hosts_info)
            
        for result in results:
            pass

        finish = time.perf_counter()
        print('Time Elapsed:', finish - starting_time)
    
def main():
    commads = cisco_command()
    hosts_info = cisco_host()
    run_program(hosts_info)


    
if __name__ == '__main__':
    main()

我不知道我错了什么

您写道:

if we run this program via multiprocessing (run_program func) the global variable can't read by open_connection func.

这个说法其实是不正确的。你的全局变量 command_info 确实被函数 open_connection 读取了。这不是问题。

我看到您遇到的问题是您正在尝试使用命令 global 来更新每个 cpu 核心 command_info 中处理的更改 运行 将 open_connection 函数添加到主核心中的全局 command_info 中。这行不通。假设您同时有 4 cpus 运行,并且每个 cpu 都试图同时修改同一个全局术语。如果 Python 允许它不允许的东西,那将是一场噩梦。

实际上,Python 允许您将 command_info 传递到每个 CPU 核心(w/o 使用全局),您可以想到 command_info现在是该计算核心独有的全局变量。要将每个唯一核心的更新 command_info 传递回 运行 concurrent.futures.ProcessPoolExecutor() 主核心,您必须在函数末尾 return command_info open_connection(host)(以及您的 sendcommand)。然后在主核心中,您可以将其作为resultsresult中的术语之一进行访问。此后,您可以更新主核心中的全局 command_info 变量。

希望这个解释能帮助您理解您的问题。 :)