3

メインの Python プログラムで subprocess を使用して Python スクリプトを開きたいと考えています。これら 2 つのプログラムが両方とも実行されているので、これら 2 つのプログラムが互いにチャットできるようにして、スレーブ スクリプトのアクティビティを監視できるようにします。つまり、相互に文字列を送信する必要があります。

メイン プログラムには、スレーブ スクリプトと通信して監視する次のような関数があります。

スクリプト 1

import subprocess
import pickle
import sys
import time
import os

def communicate(clock_speed, channel_number, frequency):
    p = subprocess.Popen(['C:\\Python27\\pythonw','test.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    data = pickle.dumps([clock_speed, channel_number, frequency]).replace("\n", "\\()")
    print data
    p.stdin.write("Start\n")
    print p.stdout.read()
    p.stdin.write(data + "\n")
    p.poll()
    print p.stdout.readline()
    print "return:" + p.stdout.readline()
    #p.kill()

if __name__ == '__main__':
    print "GO"
    communicate(clock_speed = 400, channel_number = 0, frequency = 5*1e6)

test.py スクリプトは次のようになります。

スクリプト 2

import ctypes
import pickle
import time
import sys

start = raw_input("")
sys.stdout.write("Ready For Data")
data = raw_input("")
data = pickle.loads(data.replace("\\()", "\n"))
sys.stdout.write(str(data))
###BUNCH OF OTHER STUFF###

これらのスクリプトで実行したいことは次のとおりです。

  1. Popen を使用してスクリプト 2 を開くスクリプト 1
  2. スクリプト 1 は文字列「Start\n」を送信します
  3. スクリプト 2 はこの文字列を読み取り、文字列 "Ready For Data" を送信します。
  4. スクリプト 1 はこの文字列を読み取り、ピクルス化されたデータをスクリプト 2 に送信します。
  5. じゃあなんでも…

主な問題は、パート 2 ~ 4 をどのように行うかです。その後、2 つのスクリプト間の残りの通信が続きます。今のところ、スクリプト 2 が終了した後、スクリプト 2 から文字列を読み取ることしかできませんでした。

どんな助けでも大歓迎です。

アップデート:

スクリプト 1 は 32 ビット Python を使用して実行する必要があり、スクリプト 2 は 64 ビット Python を使用して実行する必要があります。

4

2 に答える 2

4

パイプの問題は、読み取り操作を呼び出したときに読み取るものが何もない場合、相手が読み取り用に何かを書き込むまでコードが停止することです。また、書き込みが多すぎると、相手がパイプから何かを読み取って解放するまで、次の書き込み操作がブロックされる可能性があります。

これらの場合、ブロックする代わりにエラーを返す「非ブロック呼び出し」がありますが、アプリケーションは依然としてエラーを賢明に処理する必要があります。

いずれにせよ、何らかのプロトコルを設定する必要があります。HTTP、またはよく知っている他のプロトコルを考えてみてください。リクエストとレスポンスがあり、2 つのいずれかを読んでいる間、プロトコルは、他に読む必要があるかどうかを常に教えてくれます。そうすれば、さらにデータを待つかどうかについて、常に十分な情報に基づいた決定を下すことができます。

これが機能する例です。次のプロトコルがあるため、機能します。

  • p1 は '\n' で終わる 1 行を送信します。
  • p2 も同じです。
  • p1 は別の回線を送信します。
  • p2 も同じです。
  • どちらも満足して終了します。

パイプ (どちらかの側) に 1 行書き込んで、それが確実にパイプに到達するようにするために、write()andを呼び出しますflush()

パイプから 1 行 (両側) を読み取るが、それ以上 1 バイトも読み取らないようにするため、行の準備が整い、それ以上になるまでコードをブロックするには、readline().

他の呼び出しを行うことも、既成のものを含む他のプロトコルもありますが、単純なものやこのようなデモでは、単一行プロトコルがうまく機能します。

p1.py:

import subprocess

p = subprocess.Popen(['python', 'p2.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write("Hello\n")
p.stdin.flush()
print 'got', p.stdout.readline().strip()
p.stdin.write("How are you?\n")
p.stdin.flush()
print 'got', p.stdout.readline().strip()

p2.py:

import sys

data = sys.stdin.readline()
sys.stdout.write("Hm.\n")
sys.stdout.flush()
data = sys.stdin.readline()
sys.stdout.write("Whatever.\n")
sys.stdout.flush()
于 2013-03-14T01:41:15.560 に答える
0

これと同様の問題もありました。反対側がオブジェクトを送信していないか、閉じているかを知るという問題に遭遇することなく、異なるプロセス間で一般的な Python オブジェクトを送信する方法がありませんでした。また、使用しようとすることmultiprocessing.Queueは、通常、プロセスが現在のプロセスによって開始されている必要があることを意味します。これは、2 つのプロセスが協力したい場合には必ずしもそうではありません。

これに対抗するためにpicklepipe、汎用オブジェクトのシリアライゼーション パイプ インターフェイスと、 というプロトコルを使用するパイプ (これも というpickleプロトコルPicklePipemarshal使用するパイプ) を定義するモジュールを使用しますMarshalPipe。文字列だけでなく、任意の pickle 可能なオブジェクトをピアに送信できます。

パイプは選択可能です。つまり、新しいオブジェクトを受け取る準備ができたときに、パイプをselectorsモジュール (またはselectors2、 ) でファイル オブジェクトとして使用できます。selectors34これにより、多くの異なるパイプの準備が整うまでの待機が非常に効率的になります。

Python 2.7+ (およびおそらく 2.6) およびすべての主要なプラットフォームをサポートします。2 つの異なるバージョンの Python 間でオブジェクトを送信することもできます! プロジェクトのドキュメントを確認するか、Github でソースを表示してください。

開示:私はの作者ですpicklepipe。フィードバックをお待ちしております。:)

于 2016-12-29T17:15:24.960 に答える