Folding@home: Top500の日本チームを表示する改良版スクリプト

Folding@home Top 500に入っている日本チームをリストアップするPythonスクリプトを書いたが処理に30秒ぐらいかかる問題点があるとSNSで呟いたところ、チームKanazawaのメンバーNinjaさんからaiohttpとasyncioを使った並列処理プログラムを送って頂いた。許可を得て公開する。処理速度が3秒になり10倍高速になっている。チーム数がこれ以上増えた場合は、同時アクセス数を制限する必要が出てくるかもしれないという注意も頂いている。

ソースコード

import aiohttp
import asyncio
import json

JAPAN_TEAM_IDS = [162, 222, 106346, 252872, 253284, 254402, 255396, 257002,
                       257261, 257728, 258804, 259660, 260900, 261481, 263245,
                       263536, 263798, 264491]
FORMAT = '{0:>3} {1:>4} {2:<25} {3:>8} {4:>13} {5:>10}'

# cf. https://stackoverflow.com/questions/35879769/

async def fetch(session, url):
    async with session.get(url) as response:
        if response.status == 200:
            return await response.read()
        else:
            response.raise_for_status()

async def fetch_all(session, urls):
    tasks = [asyncio.create_task(fetch(session, url)) for url in urls]
    return await asyncio.gather(*tasks)

async def main():
    urls = [f'https://api.foldingathome.org/team/{team_id}'
            for team_id in JAPAN_TEAM_IDS]
    async with aiohttp.ClientSession() as session:
        teams = await fetch_all(session, urls)
        teams = [json.loads(team) for team in teams]
        teams = sorted(teams, key=lambda d: d['rank'])

        print(FORMAT.format('No', 'Rank', 'Name', 'ID', 'Score', 'Works'))
        for i, team in enumerate(teams, 1):
            if team['rank'] <= 500:
                print(FORMAT.format(i, team['rank'], team['name'], team['id'],team['score'], team['wus']))

if __name__ == '__main__':
    asyncio.run(main())

実行方法

  • 上のコードにasync_folding.pyと名前を付けて保存し、次のコマンドを実行する。実行結果は上の図である。ただし、Pythonのバージョンは3.7でなければ動かない。
    • $ python3 rank.py

終わり

コメント

タイトルとURLをコピーしました