web-dev-qa-db-ja.com

別々に実行しているPythonスクリプト間でデータを渡す

pythonスクリプトを実行し(Tkinter GUIとすべてを使用して))、収集中のライブデータ(配列などに内部的に保存されている)を別のpythonスクリプト、それを行う最良の方法は何でしょうか?

スクリプトAをスクリプトBに単にインポートすることはできません。既に実行中のスクリプトAの変数にアクセスするのではなく、スクリプトAの新しいインスタンスを作成するからです。

スクリプトAでファイルに書き込み、次にスクリプトBでファイルからデータを取得するという方法しかありません。ただし、スクリプトAが既に書き込んでいるファイルをスクリプトBが読み取ろうとすると、何か問題が発生する可能性があるため、これは理想的とは言えません。また、2つのプログラム間の通信をはるかに高速化する方法を探しています。

編集:要求された例を以下に示します。これがうまくいかない理由を私は知っていますが、それは達成する必要があることの基本的な前提です。私のソースコードは非常に長く、残念ながら機密情報であるため、ここでは役に立ちません。要約すると、スクリプトAはTkinterを実行してデータを収集していますが、スクリプトBはDjangoの一部としてのviews.pyですが、これはPythonの一部として実現できることを期待しています。

スクリプトA

import time

i = 0

def return_data():
    return i

if __name__ == "__main__":
    while True:
        i = i + 1
        print i
        time.sleep(.01)

スクリプトB

import time
from scriptA import return_data

if __name__ == '__main__':
    while True:
        print return_data()  # from script A
        time.sleep(1)
10
Jordan Gleeson

multiprocessingモジュールを使用して、2つのモジュール間にPipeを実装できます。次に、モジュールの1つをプロセスとして開始し、パイプを使用してそれと通信できます。パイプの使用についての最もよい部分は、python dictのようなオブジェクトを渡し、それをリストすることもできます。

例:mp2.py:

from multiprocessing import Process,Queue,Pipe
from mp1 import f

if __name__ == '__main__':
    parent_conn,child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    print(parent_conn.recv())   # prints "Hello"

mp1.py:

from multiprocessing import Process,Pipe

def f(child_conn):
    msg = "Hello"
    child_conn.send(msg)
    child_conn.close()
11
Akshay Apte

共有データの読み取りと変更が必要な場合は、別々に実行される2つのスクリプト間で、python multiprocessing moduleを利用して- Pipe()またはQueue() (違いを参照 here )このようにして、スクリプトを同期し、同時実行性およびグローバル変数に関する問題を回避しますスクリプトが変数を同時に変更したい場合)。

Akshay Apteが彼の回答で述べたように、パイプ/キューを使用することの最大の利点は、pythonオブジェクトを渡すことができることです。

また、まだ渡されていない場合にデータの待機を回避するメソッドもあります( queue.empty() および pipeConn.poll() )。

以下のQueue()の使用例をご覧ください。

    # main.py
    from multiprocessing import Process, Queue
    from stage1 import Stage1
    from stage2 import Stage2


    s1= Stage1()
    s2= Stage2()

    # S1 to S2 communication
    queueS1 = Queue()  # s1.stage1() writes to queueS1

    # S2 to S1 communication
    queueS2 = Queue()  # s2.stage2() writes to queueS2

    # start s2 as another process
    s2 = Process(target=s2.stage2, args=(queueS1, queueS2))
    s2.daemon = True
    s2.start()     # Launch the stage2 process

    s1.stage1(queueS1, queueS2) # start sending stuff from s1 to s2 
    s2.join() # wait till s2 daemon finishes
    # stage1.py
    import time
    import random

    class Stage1:

      def stage1(self, queueS1, queueS2):
        print("stage1")
        lala = []
        lis = [1, 2, 3, 4, 5]
        for i in range(len(lis)):
          # to avoid unnecessary waiting
          if not queueS2.empty():
            msg = queueS2.get()    # get msg from s2
            print("! ! ! stage1 RECEIVED from s2:", msg)
            lala = [6, 7, 8] # now that a msg was received, further msgs will be different
          time.sleep(1) # work
          random.shuffle(lis)
          queueS1.put(lis + lala)             
        queueS1.put('s1 is DONE')
    # stage2.py
    import time

    class Stage2:

      def stage2(self, queueS1, queueS2):
        print("stage2")
        while True:
            msg = queueS1.get()    # wait till there is a msg from s1
            print("- - - stage2 RECEIVED from s1:", msg)
            if msg == 's1 is DONE ':
                break # ends loop
            time.sleep(1) # work
            queueS2.put("update lists")             

[〜#〜] edit [〜#〜]queue.get(False) を使用してデータ受信時のブロックを回避できることがわかりました。この方法では、キューが空かどうかを最初に確認する必要はありません。パイプを使用する場合、これは不可能です。

2
onofricamila

Picklingモジュールを使用して、2つのpythonプログラム間でデータを渡すことができます。

import pickle 

def storeData(): 
    # initializing data to be stored in db 
    employee1 = {'key' : 'Engineer', 'name' : 'Harrison', 
    'age' : 21, 'pay' : 40000} 
    employee2 = {'key' : 'LeadDeveloper', 'name' : 'Jack', 
    'age' : 50, 'pay' : 50000} 

    # database 
    db = {} 
    db['employee1'] = employee1 
    db['employee2'] = employee2 

    # Its important to use binary mode 
    dbfile = open('examplePickle', 'ab') 

    # source, destination 
    pickle.dump(db, dbfile)                   
    dbfile.close() 

def loadData(): 
    # for reading also binary mode is important 
    dbfile = open('examplePickle', 'rb')      
    db = pickle.load(dbfile) 
    for keys in db: 
        print(keys, '=>', db[keys]) 
    dbfile.close() 
1
Magnus Melwin