python - 如何使用 map 函数附加到列表?

标签 python dictionary

我正在尝试使用映射将 ping_all 函数映射到主机列表。 我遇到的问题是在 ping_all 函数中,我试图将所有失败的主机附加到列表中。通常我会调用 ping_all 函数,将空列表作为参数传递并返回修改后的列表,但由于我在这里使用 map,我不确定如何实现它?

import os
import argparse
from subprocess import check_output
from multiprocessing import Pool


parser = argparse.ArgumentParser(description='test')

args = parser.parse_args()

dead_hosts = []


def gather_hosts():
    """ Returns all environments from opsnode and puts them in a dict """
    host_list = []
    url = 'http://test.com/hosts.json'
    opsnode = requests.get(url)
    content = json.loads(opsnode.text)
    for server in content["host"]:
        if server.startswith("ip-10-12") and server.endswith(".va.test.com"):
            host_list.append(str(server))
    return host_list


def try_ping(hostnames):
    try:
        hoststatus = check_output(["ping", "-c 1", hostnames])
        print "Success:", hostnames
    except:
        print "\033[1;31mPing Failed:\033[1;m", hostnames
        global dead_hosts
        dead_hosts.append(hostnames)

def show_dead_hosts(dead_hosts):
    print '\033[1;31m******************* Following Hosts are Unreachable ******************* \n\n\033[1;m'
    for i in dead_hosts:
        print '\033[1;31m{0} \033[1;m'.format(i)

if __name__ == '__main__':
    hostnames = gather_hosts()
    pool = Pool(processes=30)              # process per core
    pool.map(try_ping, hostnames, dead_hosts)
    show_dead_hosts(dead_hosts)

我尝试将 dead_hosts 作为 map 中的第二个参数传递,但在运行此脚本后,dead_hosts 仍然是一个空列表,主机似乎没有附加到列表中。

我做错了什么?

最佳答案

您的代码有几个问题:

  1. Pool.map 的第三个参数是 chunksize,因此传递 dead_hosts(列表)肯定是不正确的。
  2. 使用多处理Pool 时无法访问全局变量,因为池中的任务在不同的进程中运行。参见 Python multiprocessing global variable updates not returned to parent 了解更多详情。
  3. 与上一点相关,Pool.map 应该返回一个结果列表(因为全局副作用大部分是不可见的)。现在您只是调用它并丢弃结果。
  4. 您的格式代码在我的终端中没有正确清除,所以一切都变成了粗体+红色...

这是我更新和测试过的一个版本——我认为它可以满足您的要求:

import os
import argparse
from subprocess import check_output
from multiprocessing import Pool


parser = argparse.ArgumentParser(description='test')

args = parser.parse_args()

def gather_hosts():
    """ Returns all environments from opsnode and puts them in a dict """
    host_list = []
    url = 'http://test.com/hosts.json'
    opsnode = requests.get(url)
    content = json.loads(opsnode.text)
    for server in content["host"]:
        if server.startswith("ip-10-12") and server.endswith(".va.test.com"):
            host_list.append(str(server))
    return host_list


def try_ping(host):
    try:
        hoststatus = check_output(["ping", "-c 1", "-t 1", host])
        print "Success:", host
        return None
    except:
        print "\033[1;31mPing Failed:\033[0m", host
        return host

def show_dead_hosts(dead_hosts):
    print '\033[1;31m******************* Following Hosts are Unreachable ******************* \n\n\033[0m'
    for x in dead_hosts:
        print '\033[1;31m{0} \033[0m'.format(x)

def main():
    hostnames = gather_hosts()
    pool = Pool(processes=30)              # process per core
    identity = lambda x: x
    dead_hosts = filter(identity, pool.map(try_ping, hostnames))
    show_dead_hosts(dead_hosts)

if __name__ == '__main__':
    main()

我所做的主要更改是 try_ping 要么在成功时返回 None,要么在失败时返回 host 的名称。 ping 由您的任务池并行完成,结果聚合到一个新列表中。我在列表上运行一个 filter 以去除所有 None 值(None 在 Python 中是“falsey”),只留下未通过 ping 测试的主机名。

您可能希望摆脱 try_ping 中的 print 语句。我假设您只有那些用于调试的。

如果您需要更多的异步性,您还可以考虑使用 imapifilter

关于python - 如何使用 map 函数附加到列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36510412/

相关文章:

python - jedi-vim 是否与 YouCompleteMe 冲突?

javascript - 查找数组中最后一个带有键的字典

C++模板类映射

list - Ansible:如何将默认值应用于列表的每个复杂参数

python - 使用 Python 绑定(bind),Selenium WebDriver click() 有时无法正常工作。

python - 对 Pandas 数据框中的行对执行函数

python - 如何将大数据从任何文件系统迁移到 plone 站点 plone 4.1?

python - Mongo 条件为 "key doesn' t 存在”?

python - 如何选择深度嵌套的键 :values from dictionary in python

java - 如何将 jdbcTemplate.queryForList 语句作为 List<Map<String, Object>> 传递给另一个方法