2017-04-14 8 views
0

私の指先をPythonの非同期プログラミングに突き刺し、面白いアプリケーションに遭遇して、どこのマシンが~100台のマシンで約10個のファイルにファイルサイズを集める必要があるのかログファイルを適切にパージしません。非同期コルーチンが終了していないようです

私の同期アプローチがあった。これは素晴らしい作品が、これらすべてのグロブや統計情報を引っ張っネットワークオペレーションとの長い時間を要する

File_info = namedtuple("File_info", "machineinfo size") 

machines = utils.list_machines() # the computers being queried 
# each machine object has attributes like "name", "IP", and "site_id" among others 

file_sizes = {} 
# {filename: [File_info, ...], ...} 

for m in machines: 
    print(f"Processing {m}...") # this is "Processing {m}...".format(m=m) 
           # isn't Python 3.6 awesome?! 
    for path in glob.glob(f"//{m.IP}/somedir/*.dbf"): 
     fname = os.path.split(path)[-1].lower() 
     machineinfo = (m.site_id, m.name) 
     size = os.stat(path).st_size 
     file_sizes.setdefault(fname, []).append(File_info(registerinfo, size)) 

。 Python 3.5のasync/aswait構文をasyncioで使用して、これらの呼び出しを非同期にしたかったのです。スクリプトは、外側loop.run_until_completeセクション内ハングしかし

File_info = namedtuple("File_info", "machineinfo size") 

machines = utils.list_machines() 

file_sizes = {} 
# {filename: [File_info, ...], ...} 

async def getfilesizes(machine, loop): 
    machineinfo = machine.site_id, machine.name 
    paths = glob.glob(f"//{machine.IP}/somedir/*.dbf") 
    coros = [getsize(path) for path in paths] 
    results = loop.run_until_complete(asyncio.gather(*coros)) 
    sizes = {fname: File_info(machineinfo, size) for (fname, size) in results} 
    return sizes 

async def getsize(path): 
    return os.path.split(path)[-1], os.stat(path).st_size 

loop = asyncio.get_event_loop() 
results = loop.run_until_complete(asyncio.gather(*(getfilesizes(m, loop) for m in machines))) 
for result in results: 
    file_sizes.update(result) 
    # I have a problem here since my dict values are lists that need to extend 
    # not overwrite, but that's not relevant for the error I'm getting 

:ここに私が思い付いたものです。私は間違って何をしていますか?

+0

別のコルーチンを実行したり、将来の結果を得たいコルーチンは、 'run_until_complete'と一緒にそれを送信しないで' await'することになっています。 – user2357112

+0

「asyncio.gather(...)を待つべきですか? –

+0

@ user2357112よく私は猿の叔父になるでしょう、それは簡単でした。どうして私が 'asyncio.gather'が' Future'オブジェクトを1つ与えるという接続をしなかったのか分かりませんので、スケジューリングするのではなく、ただ離れてしまいます。それを答えとして書きますか?さもなければ、私は自己答えます。 –

答えて

0

別のコルーチンを実行したいコルーチン(getfilesizesgetsizeと同じです)は、イベントループでスケジューリングするのではなく、awaitにする必要があります。

... 

async def getfilesizes(machine): # changed func sig 
    machineinfo = machine.site_id, machine.name 
    paths = glob.glob(f"//{machine.IP}/somedir/*.dbf") 
    coros = [getsize(path) for path in paths] 
    results = await asyncio.gather(*coros) # await the results instead! 
    sizes = {fname: File_info(machineinfo, size) for (fname, size) in results} 
    return sizes 

... 

asyncio.gatherがコルーチンの任意の数から1人の未来を作成するので、このawaitは機能コルーチンのグループ全体に作用し、一度にすべての結果をつかみます。

関連する問題