Thread処理と非同期処理をやってみた(Python)

並行処理としてマルチプロセス処理、並列処理としてThread処理、非同期処理がある。 Python multiprocessing vs threading vs asyncio - JX通信社エンジニアブログ

今回はThread処理、非同期処理について実行した備忘録となる。

方法

Threadクラスを継承する

Python3でマルチスレッド処理を試してみる - Corgi Lab. ~備忘録のための技術ブログ~

Threadクラスのインスタンスをつくる

Python3でマルチスレッド処理を試してみる - Corgi Lab. ~備忘録のための技術ブログ~

import time
import threading

def proc():
    for i in range(0,5):
        time.sleep(1)
        print("count", i)

if __name__ == '__main__':
    th1 = threading.Thread(target=proc)
    th2 = threading.Thread(target=proc)
    th1.start()
    th2.start()

クラスの中で更にスレッド処理させようとも試みたがうまく行かなかった。

非同期I/Oを利用する

非同期I/Oでやってみたコードが下記。 iPerf Client / Serverを実行し、結果をリアルタイムに取得する。

# 5.2. プロセス生成: SSHClientConnection.create_process()
# https://blog.hoxo-m.com/entry/asyncssh

import asyncio, asyncssh, sys, getpass

async def async_ssh(cmd):
    pw = "password"
    async with asyncssh.connect("localhost", username='user',password=pw) as conn:
        if "-c" in cmd: await asyncio.sleep(1)
        async with conn.create_process(cmd, stdout=sys.stdout) as process:
            await process.wait()

try:
    iperf_srv = "iperf -s -u -i1 -t5"
    iperf_cli = "iperf -u -c localhost -i1 -t5"
    gather = asyncio.gather(
        async_ssh(iperf_srv),
        async_ssh(iperf_cli)
    )
    asyncio.get_event_loop().run_until_complete(gather)   
    #loop = asyncio.get_event_loop()
    
except (OSError, asyncssh.Error) as exc:
    sys.exit('SSH connection failed: ' + str(exc))

孫クラスからThreadクラスのinit()をコール

ベースクラスとしてThreadクラスを持たせ、その孫クラスにてスレッドを実行する場合を書く。

Threadクラスを継承するaクラス、aクラスを継承するbクラス、bクラスを継承するcクラスといった構成にて、 それぞれIinit()コンストラクタが設定されている場合、各々init()をオーバーライトしているため、 最下のcクラスからThreadクラスのinit()をコールする事ができない。

この場合、Threadクラスのinit()をコールするためには、各クラスで上位クラスのコンストラクタをコールすればよい。

#a.py
import threading

class a(threading.Thread):
    def __init__(self):
        print('a')
        super().__init__()
#b.py
from a import a

class b(a):
    def __init__(self):
        print('b')
        super().__init__()
#c.py
from b import b
import threading
import time

class c(b):
    def __init__(self,name):
        print('c',name)
        self.__name = name
        super().__init__()

    def run(self):
        while 1:
            print('c-loop',self.__name)
            time.sleep(1)

if __name__ == '__main__' :
    c1=c('c1')
    c1.start()
    c2=c('c2')
    c2.start()

余談

余談だが、クラス図の作成はpylintを用いて作成した。

pyreverse -o png . -A -f ALL

オプションを設定しないと全クラスやプライベート変数を表示できないため、-Aで全クラス、-fでプライベート変数を表示する。 参考:Python でパッケージやクラス間の依存関係を可視化してみた.[Pyreverse] - 人生ゲーム - 限界理系大学院生の日々の呟き

参考