2016-04-08 17 views
1

マップを使用して、ping_all関数をホストのリストにマップしようとしています。 問題は、ping_all関数の中で、すべての失敗したホストをリストに追加しようとしていることです。通常、私はping_all関数を呼び出し、引数として空のリストを渡し、変更されたリストを返しますが、ここでマップを使用しているので、それを達成する方法がわかりません。マップ機能を使用してリストに追加するにはどうすればよいですか?

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) 

私はマップに2番目の引数としてdead_hostsを渡してみましたが、このスクリプトを実行した後、dead_hostsは空のリストのまま、ホストがリストに追加されていることを表示されません。

私は間違っていますか?

答えて

1

は、あなたのコードでいくつかの問題があります。

  1. Pool.mapへの3番目の引数がそうdead_hosts(リスト)を渡し、chunksizeで間違いなく間違っています。
  2. マルチプロセスPoolを使用している場合は、プール内のタスクが別々のプロセスで実行されるため、グローバルにアクセスすることはできません。詳細については、Python multiprocessing global variable updates not returned to parentを参照してください。
  3. これに関連して、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はPythonでは "falsey")、pingテストに失敗したホスト名だけを残します。

    try_pingprintの文を取り除きたいと思うかもしれません。私はあなたがデバッグ用のものを持っていたと仮定しています。

    さらに非同期が必要な場合は、とifilterを使用することもできます。

  • +0

    identity = lambda行のポイントは何ですか? – david

    +0

    私はちょうどそれがアイデンティティラムダを直接フィルタ呼び出しに置くことよりも読みやすいと思った。あなたが好きなら、それはもちろんインラインにすることができます。 – DaoWen

    +0

    しかし、私はなぜこの行が必要であるのか分かりません – david

    0

    try_ping関数は実際に何も返しません。私があなただったら、dead_hostsを関数の外に持っていてもtry_ping関数の中では気にしません。そして、あなたはそのリストreturnする必要があります。

    私は使用しているモジュールに慣れていないので、pool.mapがリストを取得できるかどうかわかりません。

    関連する問題