目次
スレッドは実行の最小単位であり、プロセスは少なくとも1つのスレッドで構成されます。
マルチプログレス
Unix / Linuxオペレーティングシステムはfork()
システムコールを提供します。これはfork()
、オペレーティングシステムが現在のプロセス(親プロセスと呼ばれる)(子プロセスと呼ばれる)のコピーを自動的に作成し、次に親プロセスで個別に作成するため、1回呼び出されて2回返されます。プロセスと子プロセス内に戻ります。
子プロセスは常にを返し0
、親プロセスは子プロセスのIDを返します。これは、親プロセスが多くの子プロセスをフォークできるためです。したがって、親プロセスは各子プロセスのIDを記録する必要があり、子プロセスgetppid()
は親プロセスIDを取得するために呼び出すだけで済みます。
Pythonos
モジュールは一般的なシステムコールをカプセル化します
import os
print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork()
if pid == 0:
print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
else:i
print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
操作の結果は次のとおりです。
Process (876) start...
I (876) just created a child process (877).
I am child process (877) and my parent is 876.
multiprocessing
このモジュールは、プロセスオブジェクトを表すProcess
クラスを提供します。次の例は、子プロセスを開始し、その終了を待つ方法を示しています。
groupパラメーターは使用されず、値は常にNoneです。
ターゲットは、子プロセスによって実行されるタスクである、呼び出されたオブジェクトを表します。
nameは子プロセスに名前を付けることができます。
argsは、ターゲット関数の位置パラメーターを指定します。これはタプル形式であり、次のようにコンマを使用する必要があります。args=( 'monicx'、)
kwargsは、kwargs = {'name': 'monicx'、 'age':18}などの辞書であるターゲット関数のキーワードパラメーターを指定します。
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('Child process will start.')
p.start()
p.join()
print('Child process end.')
実行結果は以下のとおりです。
Parent process 928.
Child process will start.
Run child process test (929)...
Process end.
クラスProcessをインスタンス化して、子プロセスを作成します
Processクラスのメソッドは次のとおりです。
start():プロセスを開始し、子プロセスでp.run()を呼び出します
run():プロセスを開始して実行するためのメソッドは、ターゲットで指定された関数を呼び出すことです。このメソッドは、カスタムクラスのクラスに実装する必要があります。
terminal():プロセスを強制的に終了します。クリーンアップ操作は実行されません。pが子プロセスを作成すると、子プロセスはゾンビプロセスになります。この方法を使用して注意してください。プロセスがまだロックを保持している場合、ロックは解放されず、デッドロックが発生します。 。。
is_alive():プロセスが「生きている」かどうかを判別します。
join(timeout):メインスレッドが子プロセスの終了を待ってから、メインプロセスの実行を続行します。タイムアウトはオプションのタイムアウト期間です。メインプロセスは複数回待機しません。
方法2:継承を通じてプロセスを実現します。
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super(MyProcess,self).__init__()
self.name=name
def run(self):
print("%s is running " %self.name)
time.sleep(2)
print('%s is done'%self.name)
if __name__ == '__main__':
p=MyProcess('monicx')
p.start()#就是调用run()方法。
print('====主')
运行结果:
====主
monicx is running
monicx is done
プール
多数の子プロセスを開始する場合は、プロセスプールメソッドを使用して、子プロセスをバッチで作成できます。
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4)
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')
実行結果は以下のとおりです。
Parent process 669.
Waiting for all subprocesses done...
Run task 0 (671)...
Run task 1 (672)...
Run task 2 (673)...
Run task 3 (674)...
Task 2 runs 0.14 seconds.
Run task 4 (673)...
Task 1 runs 0.27 seconds.
Task 3 runs 0.86 seconds.
Task 0 runs 1.41 seconds.
Task 4 runs 1.91 seconds.
All subprocesses done.
join()
あなたは必要があります 呼び出しを呼び出す前にclose()
、close()
あなたは後に新しいものを追加することはできません呼び出しますProcess
。
子プロセス
子プロセスはそれ自体ではなく、外部プロセスです。子プロセスを作成した後、子プロセスの入力と出力も制御する必要があります。
subprocess
モジュールは子プロセスを簡単に開始し、その入力と出力を制御できます。multiprocessing
基盤となるメカニズムをパッケージ化したPythonモジュールにはQueue
、Pipes
データを交換するためのさまざまな方法が用意されています。
from multiprocessing import Process, Queue
import os, time, random
# 写数据进程执行的代码:
def write(q):
print('Process to write: %s' % os.getpid())
for value in ['A', 'B', 'C']:
print('Put %s to queue...' % value)
q.put(value)
time.sleep(random.random())
# 读数据进程执行的代码:
def read(q):
print('Process to read: %s' % os.getpid())
while True:
value = q.get(True)
print('Get %s from queue.' % value)
if __name__=='__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 启动子进程pr,读取:
pr.start()
# 等待pw结束:
pw.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
pr.terminate()
操作の結果は次のとおりです。
Process to write: 50563
Put A to queue...
Process to read: 50564
Get A from queue.
Put B to queue...
Get B from queue.
Put C to queue...
Get C from queue.
subprocess.call(cmd、shell = True)
子プロセスを開始して実行し、子プロセスの終了を待ってから他のプロセスの実行を続行します
パラメータで指定されたコマンドを実行します。パラメータとして配列を使用してコマンドを実行することも、パラメータとして文字列を使用してコマンドを実行することもできます。
0、1を返します
nslookupは、ネットワーク内のサーバーがドメイン名の解決を正しく実装できるかどうかを検出するコマンドラインツールです。
import subprocess
r = subprocess.call(['nslookup', 'www.python.org'])
print('Exit code:', r)
#输出
Server: 192.168.19.4
Address: 192.168.19.4#53
Non-authoritative answer:
www.python.org canonical name = python.map.fastly.net.
Name: python.map.fastly.net
Address: 199.27.79.223
Exit code: 0
それでも子プロセスに入力が必要な場合は、次のcommunicate()
方法で入力できます。
import subprocess
print('$ nslookup')
p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate(b'set q=mx\npython.org\nexit\n')
print(output.decode('utf-8'))
print('Exit code:', p.returncode)
上記のコードは、コマンドラインでコマンドを実行してからnslookup
手動で入力するのと同じです。
set q=mx
python.org
exit
操作の結果は次のとおりです。
$ nslookup
Server: 192.168.19.4
Address: 192.168.19.4#53
Non-authoritative answer:
python.org mail exchanger = 50 mail.python.org.
Authoritative answers can be found from:
mail.python.org internet address = 82.94.164.166
mail.python.org has AAAA address 2001:888:2000:d::a6
Exit code: 0