Python のプロセスに引数を渡す
Python のマルチプロセスでは、Process クラスの args と kwargs 引数を使って子プロセスにデータを渡します。ただし、プロセス間ではメモリが共有されないため、データの受け渡し方法を理解しておくことが重要です。
位置引数を渡す
args にタプルを指定して、位置引数を渡します。
from multiprocessing import Process
def greet(name, age):
print(f"Hello, {name}! You are {age} years old.")
if __name__ == "__main__":
p = Process(target=greet, args=("Alice", 25))
p.start()
p.join()
引数が 1 つの場合でも、タプルとして渡す必要があります。args=("Alice",) のようにカンマを忘れないでください。
キーワード引数を渡す
kwargs に辞書を指定して、キーワード引数を渡します。
from multiprocessing import Process
def configure(host, port, debug=False):
print(f"Server: {host}:{port}, debug={debug}")
if __name__ == "__main__":
p = Process(
target=configure,
args=("localhost", 8080),
kwargs={"debug": True}
)
p.start()
p.join()
args と kwargs を組み合わせて使うこともできます。
オブジェクトを渡す
リストや辞書などのオブジェクトも引数として渡せます。
from multiprocessing import Process
def process_data(data):
for item in data:
print(f"Processing: {item}")
if __name__ == "__main__":
my_list = [1, 2, 3, 4, 5]
p = Process(target=process_data, args=(my_list,))
p.start()
p.join()
渡されたオブジェクトは pickle でシリアライズされてコピーされます。子プロセス内で変更しても、親プロセスのオブジェクトには影響しません。
引数の変更は親プロセスに反映されない
プロセス間ではメモリが独立しているため、子プロセスで引数を変更しても親には反映されません。
from multiprocessing import Process
def modify_list(data):
data.append(100)
print(f"Child: {data}")
if __name__ == "__main__":
my_list = [1, 2, 3]
p = Process(target=modify_list, args=(my_list,))
p.start()
p.join()
print(f"Parent: {my_list}") # [1, 2, 3] のまま
親プロセスがリストを渡す
子プロセスにコピーが作られる
子プロセスでコピーを変更
親のリストは変更されない
データを共有したい場合は、Queue、Pipe、Value、Array、Manager などを使います。
pickle できないオブジェクトに注意
引数は pickle でシリアライズされるため、pickle できないオブジェクトは渡せません。
from multiprocessing import Process
def worker(func):
func()
if __name__ == "__main__":
# ラムダ式は pickle できない
p = Process(target=worker, args=(lambda: print("Hello"),))
p.start() # エラーになる
p.join()
ラムダ式やローカル関数は pickle できないため、代わりにモジュールレベルの関数を定義して使います。
大量のデータを渡す場合
大きなデータを引数で渡すと、シリアライズとコピーのコストがかかります。
大量のデータを効率的に扱いたい場合は、これらの方法を検討してください。