我正在尝试使用map,将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仍然是一个空列表,看起来主机没有附加到列表中。
我做错了什么?
答案 0 :(得分:1)
您的代码存在以下问题:
Pool.map
的第三个参数是chunksize
,因此传递dead_hosts
(列表)肯定是不正确的。Pool
时,您无法访问全局变量,因为池中的任务在不同的进程中运行。有关详细信息,请参阅 Python multiprocessing global variable updates not returned to parent 。Pool.map
应该返回一个结果列表(因为全局副作用基本上是不可见的)。现在你只是打电话给它并扔掉了结果。这是我更新和测试过的版本 - 我认为它符合您的要求:
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
在" falsey"在Python中),只留下失败的主机名ping测试。
您可能希望摆脱print
中的try_ping
语句。我假设您只是用于调试。
如果您需要更多异步,也可以考虑使用imap
和ifilter
。
答案 1 :(得分:0)
您的try_ping
函数实际上没有返回任何内容。如果我是你,我不会在函数之外但在try_ping函数内部使用dead_hosts
。然后你应该return
该列表。
我不熟悉您正在使用的模块,因此我不知道pool.map
是否可以使用列表。