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)
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()
共有データの読み取りと変更が必要な場合は、別々に実行される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) を使用してデータ受信時のブロックを回避できることがわかりました。この方法では、キューが空かどうかを最初に確認する必要はありません。パイプを使用する場合、これは不可能です。
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()