Skip to content

python2 マルチプロセス#

from multiprocessing import Process

def worker():
    print('Worker process')

if __name__ == '__main__':
    # プロセスの生成
    p = Process(target=worker)

    # プロセスの開始
    p.start()

    # プロセスの終了待ち
    p.join()

    print('Main process')
from multiprocessing import Process, Queue

def worker(q):
    result = 'result'
    q.put(result)

if __name__ == '__main__':
    # キューの生成
    q = Queue()

    # プロセスの生成
    p = Process(target=worker, args=(q,))

    # プロセスの開始
    p.start()

    # キューから結果を取得
    result = q.get()

    # プロセスの終了待ち
    p.join()

    print(result)

この例では、workerプロセスでresultという文字列を生成し、Queueに格納しています。親プロセスでは、Queueから結果を取得しています。 argsパラメータを使用して、worker関数に引数としてQueueオブジェクトを渡しています。

Queueを使用することで、複数のプロセスが同時に結果を書き込むことができ、親プロセスはそれらの結果を順番に取り出すことができます。 ただし、Queueはシリアライズ可能なオブジェクトしか格納できないため、戻り値がシリアライズ可能であることを確認する必要があります。

特定のファイル名とパスを取得する#

Python 2で正規表現を使用して複数のディレクトリに対してファイルを検索するには、reモジュールを使用して正規表現パターンをコンパイルし、osモジュールを使用してディレクトリを検索する必要があります。以下はその方法の例です。

import os
import re
from multiprocessing import Pool

def find_files(directory, pattern):
    results = []
    regex = re.compile(pattern)
    for root, dirs, files in os.walk(directory):
        for file in files:
            if regex.search(file):
                results.append(os.path.join(root, file))
    return results

if __name__ == '__main__':
    directories = ['/path/to/dir1', '/path/to/dir2', '/path/to/dir3']
    pattern = r'target_file\d+\.txt'
    pool = Pool()
    results = []
    for directory in directories:
        result = pool.apply_async(find_files, args=(directory, pattern))
        results.append(result)
    pool.close()
    pool.join()
    for result in results:
        file_paths = result.get()
        for file_path in file_paths:
            print(directory, file_pat

この例では、find_files関数を定義し、ディレクトリと正規表現パターンを受け取って、 指定されたディレクトリ以下のファイルを検索し、指定された正規表現パターンにマッチするファイルのパスをリストに格納しています。

os.walk関数を使用して、ディレクトリ以下のすべてのファイルを再帰的に検索しています。re.compile関数を使用して、 指定された正規表現パターンをコンパイルしています。searchメソッドを使用して、ファイル名が正規表現パターンにマッチするかどうかを判定しています。

親プロセスでは、複数のディレクトリに対してPoolクラスを使用してマルチプロセスを実行しています。 apply_asyncメソッドを使用して、find_files関数を非同期で呼び出し、結果をresultsリストに追加しています。 closeメソッドを呼び出して、新しいタスクを追加しないようにします。joinメソッドを呼び出して、すべてのタスクが完了するまで待ちます。

最後に、resultsリストから結果を取得して、それぞれのディレクトリにある指定された正規表現パターンにマッチするファイルのパスを出力します。 getメソッドを使用して、非同期で実行された各タスクの結果を取得しています。

例2#

Python 2で特定の文字列が含まれるファイルを複数のディレクトリから取得し、 リストに保存するために、multiprocessingモジュールを使用してマルチプロセス処理を行います。

以下にコード例を示します。

import os
import multiprocessing

def find_files_with_string(root_dir, target_string):
    result = []
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for filename in filenames:
            file_path = os.path.join(dirpath, filename)
            try:
                with open(file_path, 'r') as file:
                    content = file.read()
                    if target_string in content:
                        result.append(file_path)
            except IOError:
                pass
    return result

def process_directory(root_dir, target_string, output):
    files = find_files_with_string(root_dir, target_string)
    output.extend(files)

if __name__ == '__main__':
    root_dirs = ['/path/to/dir1', '/path/to/dir2', '/path/to/dir3']
    target_string = 'target'

    manager = multiprocessing.Manager()
    output = manager.list()

    processes = []
    for root_dir in root_dirs:
        p = multiprocessing.Process(target=process_directory, args=(root_dir, target_string, output))
        p.start()
        processes.append(p)

    for p in processes:
        p.join()

    result_list = list(output)
    print(result_list)

上記のコードでは、find_files_with_string関数が指定したディレクトリから特定の文字列を含むファイルを見つけ、リストに保存します。

process_directory関数は各ディレクトリごとに呼び出され、find_files_with_stringを実行して結果をoutputリストに追加します。

main関数では、処理するルートディレクトリのリストroot_dirsと、検索する文字列target_stringを設定します。

multiprocessing.Manager()を使用して共有リストoutputを作成し、各ディレクトリを処理するためのプロセスを作成します。

各プロセスは並行して実行され、最終的に結果がoutputに追加されます。最後に、outputリストを通常のリストに変換して結果を表示します。

必要に応じて、root_dirsを適切なディレクトリパスのリストに変更してください。また、target_stringを検索したい文字列に置き換えてください。

ファイルを開く処理を追加#

以下のコードは、マルチプロセスを使用してファイルのパスからファイルを開き、特定の文字列が含まれるかどうかを確認し、結果をリストに保存する方法を示しています。

import os
import multiprocessing

def find_files_with_string(root_dir, target_string):
    result = []
    for dirpath, dirnames, filenames in os.walk(root_dir):
        for filename in filenames:
            file_path = os.path.join(dirpath, filename)
            try:
                with open(file_path, 'r') as file:
                    content = file.read()
                    if target_string in content:
                        result.append(file_path)
            except IOError:
                pass
    return result

def process_file(file_path, target_string, output):
    try:
        with open(file_path, 'r') as file:
            content = file.read()
            if target_string in content:
                output.append(file_path)
    except IOError:
        pass

if __name__ == '__main__':
    root_dirs = ['/path/to/dir1', '/path/to/dir2', '/path/to/dir3']
    target_string = 'target'

    manager = multiprocessing.Manager()
    output = manager.list()

    files = []
    for root_dir in root_dirs:
        files.extend(find_files_with_string(root_dir, target_string))

    processes = []
    for file_path in files:
        p = multiprocessing.Process(target=process_file, args=(file_path, target_string, output))
        p.start()
        processes.append(p)

    for p in processes:
        p.join()

    result_list = list(output)
    print(result_list)

このコードでは、find_files_with_string関数は特定のディレクトリからファイルを探し、リストに保存します(前のコードと同じ)。

process_file関数は各ファイルのパスを受け取り、ファイルを開いて特定の文字列が含まれるかどうかを確認し、結果をoutputリストに追加します。

メインの処理では、root_dirsとtarget_stringを設定し、filesリストに対象のファイルパスを格納します。

その後、各ファイルに対してprocess_file関数を実行するためのプロセスを作成します。

各プロセスは並行して実行され、結果がoutputに追加されます。最後に、outputリストを通常のリストに変換して結果を表示します。

同様に、root_dirsを適切なディレクトリパスのリストに変更し、target_stringを検索したい文字列に置き換えてください。

例3#

Python 2では、multiprocessingモジュールを使用してマルチプロセスを実装することができます。以下のコードは、Python 2でクラス内にマルチプロセスのクラスメソッドを実装する例です。

import multiprocessing

class MyClass(object):
    @staticmethod
    def my_method(arg1, arg2):
        # マルチプロセスで実行されるメソッド
        # ここに処理を記述します
        print("Process ID:", multiprocessing.current_process().pid)
        print("Arguments:", arg1, arg2)

    def run_in_parallel(self):
        # プロセスのリスト
        processes = []

        # プロセスを生成して開始する
        for i in range(5):
            p = multiprocessing.Process(target=self.my_method, args=(i, i+1))
            p.start()
            processes.append(p)

        # 全てのプロセスが終了するまで待つ
        for p in processes:
            p.join()

if __name__ == '__main__':
    obj = MyClass()
    obj.run_in_parallel()

上記のコードでは、MyClassというクラスを定義し、my_methodというメソッドをマルチプロセスで実行する方法を示しています。run_in_parallelメソッドは、my_methodを複数のプロセスで実行するためのものです。

run_in_parallelメソッドでは、multiprocessing.Processを使用して複数のプロセスを生成し、my_methodを呼び出しています。各プロセスは、argsパラメーターを使用して引数を渡します。

startメソッドでプロセスを開始し、joinメソッドで全てのプロセスが終了するまで待ちます。

注意点として、Python 2ではmultiprocessingモジュールを使用する場合、クラスメソッドを直接実行することはできません。そのため、my_methodを通常のメソッドとして定義し、selfパラメーターを受け取るようにしています。

@staticmethod#

@staticmethodは、Pythonのデコレーター(Decorator)の一種です。クラス内でメソッドを定義する際に使用され、静的メソッド(Static Method)として振る舞うようにします。

静的メソッドは、特定のインスタンスに依存しない一般的な操作を実行するために使用されます。インスタンス変数やインスタンスメソッドにアクセスする必要がなく、クラスレベルでの操作を実行します。

静的メソッドは以下のように定義されます。

class MyClass(object):
    @staticmethod
    def my_static_method(arg1, arg2):
        # 静的メソッドの処理
        pass

上記の例では、my_static_methodが静的メソッドとして定義されています。静的メソッドは、@staticmethodデコレーターに続いてメソッドを定義することでマークされます。

静的メソッドは、インスタンスを作成せずにクラス名を介して直接呼び出すことができます。インスタンスメソッドと異なり、selfパラメーターは持ちません。そのため、静的メソッド内ではクラス変数やインスタンス変数に直接アクセスすることはできません。

以下は、静的メソッドを使用する例です。

class MathUtils(object):
    @staticmethod
    def add_numbers(a, b):
        return a + b

result = MathUtils.add_numbers(3, 5)
print(result)  # 結果: 8

上記の例では、MathUtilsクラス内にadd_numbersという静的メソッドを定義しています。このメソッドは2つの引数を受け取り、それらを加算して結果を返します。静的メソッドはインスタンスを作成する必要がなく、クラス名を介して直接呼び出すことができます。したがって、MathUtils.add_numbers(3, 5)のように使用できます。

静的メソッドは、クラスのユーティリティ関数や共有の処理を実装する際に便利です。インスタンスに関連しない操作を行う必要がある場合に使用すると良いでしょう。