別のファイル/スクリプトをスレッド化または書き込むことなく、サブプロセスで関数を実行することは可能ですか?


83
import subprocess

def my_function(x):
    return x + 100

output = subprocess.Popen(my_function, 1) #I would like to pass the function object and its arguments
print output 
#desired output: 101

個別のスクリプトを使用してサブプロセスを開くことに関するドキュメントしか見つかりませんでした。関数オブジェクトを渡す方法や、関数コードを渡す簡単な方法を知っている人はいますか?


1
あなたはマルチプロセッシングモジュールを探していると思います。
ノクティススカイタワー2010年

回答:


112

マルチプロセッシングモジュールのようなものを探していると思います。

http://docs.python.org/library/multiprocessing.html#the-process-class

サブプロセスモジュールは、プロセスを生成し、その入力/出力を使用して処理を行うためのものであり、関数を実行するためのものではありません。

ここでmultiprocessingあなたのコードのバージョンは:

from multiprocessing import Process, Queue

# must be a global function    
def my_function(q, x):
    q.put(x + 100)

if __name__ == '__main__':
    queue = Queue()
    p = Process(target=my_function, args=(queue, 1))
    p.start()
    p.join() # this blocks until the process terminates
    result = queue.get()
    print result

20
processifyデコレータをショートカットとして使用できます:gist.github.com/2311116
schlamar

3
これは、Pythonインタープリターとそのサブプロセスのすべての環境のクローンを作成すると思いますか?
イェンス

1
これは、Python 3で機能し、ジェネレーター関数をサポートするprocessifyのフォークです。 gist.github.com/stuaxo/889db016e51264581b50
Stuart Axon

4
このコードには、自明ではない大きなデータをキューに渡す場合のデッドロックが含まれていることに注意してください。プロセスに参加する前に常にqueue.get()を渡してください。そうしないと、何も読み取っていないときにキューに書き込もうとしてハングします。
Petr Baudis 2017年

@schlamarバックグラウンドで関数を実行したいのですが、リソースに制限があり、関数を何度でも実行できず、関数の追加の実行をキューに入れたいと思っています。私がそれをどのようにすべきかについて何か考えがありますか?ここに質問があります。私の質問を見ていただけませんか。どんな助けでも素晴らしいでしょう!
アミール

17

標準のUnixforkシステムコールをとして使用できますos.fork()fork()同じスクリプトを実行して、新しいプロセスを作成します。新しいプロセスでは0を返し、古いプロセスでは新しいプロセスのプロセスIDを返します。

child_pid = os.fork()
if child_pid == 0:
  print "New proc"
else:
  print "Old proc"

複数のプロセスを使用するための移植可能な抽象化を提供するマルチプロセッシングサポートを提供する高レベルのライブラリには、マルチプロセッシングモジュールがあります。IBM DeveloperWorks、Pythonを使用したマルチプロセッシングに関する記事があり、両方の手法について簡単に紹介しています。


私は興味がある; なぜ反対票を投じるのですか?私の答えに何か問題がありますか?
ブライアンキャンベル

マルチプロセッシングは、fork()の単なる高レベルのラッパーではなく、マルチプラットフォームのマルチプロセッシングツールキットです(unixでforkを使用します)。これは重要です。これは、たとえばWindowsで実行されるのに対し、fork()は実行されないことを意味します。編集:そしてこれが反対票の理由でしたが、後でそれはおそらく価値がないと判断しました。しかし、それを取り戻すには遅すぎます。Edit2:むしろ、クロスプラットフォームでないときにfork()が提案されたことが理由でした。
Devin Jeanpierre 2010年

3
@Devin、必要に応じて、いつでも反対票を取り戻すことができます。
Alex Martelli 2010年

それを明確にするために編集しました。forkポータブルではないことを明示的に述べました。私は通常、移植性のない回答と、移植性がないという情報を提供し、質問者にそれで十分かどうかを判断させます。私が答えを編集したので、私がそれを十分に改善したと感じたら、あなたは反対票を取り除くことができるはずです。そうしなければつらい気持ちはありませんが、何が間違っているのかを確認したかっただけです。
ブライアンキャンベル

@アレックス、いや、できません。一定の時間が経過すると、編集が行われるまで元に戻すことはできません。私が再考する前にそのような時間が経過したので、「遅すぎる」というコメント。とにかく、私が言ったように、私はそれが価値がないと判断したので、それはなくなりました。私もあなたの理由に感謝し、理解しています、そして私はどちらの方法でも難しい感情がないことを嬉しく思います。:p
Devin Jeanpierre 2010年

5

マルチプロセッシングに関するBrianMcKennaの上記の投稿は非常に役立ちますが、(プロセスベースではなく)スレッド化されたルートをたどりたい場合は、次の例を参考にしてください。

import threading
import time

def blocker():
    while True:
        print "Oh, sorry, am I in the way?"
        time.sleep(1)

t = threading.Thread(name='child procs', target=blocker)
t.start()

# Prove that we passed through the blocking call
print "No, that's okay" 

このsetDaemon(True)機能を使用して、スレッドをすぐにバックグラウンド化することもできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.