如果我运行了一个python脚本(使用完整的Tkinter GUI和所有内容)并且我想传递实时数据,它正在收集(内部存储在数组等中)到另一个python脚本,这将是最好的方法是什么?
我不能简单地将脚本A导入脚本B,因为它将创建脚本A的新实例,而不是访问已经运行的脚本A中的任何变量。
我能想到的唯一方法是让脚本A写入文件,然后脚本B从文件中获取数据。这不太理想,但是如果脚本B试图读取脚本A已经写入的文件,可能会发生不好的事情。此外,我正在寻找更快的速度来实现两个程序之间的通信。
修改 以下是所要求的示例。我知道为什么这不起作用,但它是需要实现的基本前提。我的源代码非常长,不幸的是保密,因此在这里没有帮助。总之,脚本A运行Tkinter并收集数据,而脚本B是views.py作为Django的一部分,但我希望这可以作为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)
答案 0 :(得分:8)
您可以使用multiprocessing
模块在两个模块之间实现Pipe
。然后,您可以将其中一个模块作为Process启动,并使用Pipe与之通信。关于使用管道的最好的部分是你也可以传递像dict这样的python对象,通过它进行列表。
例: 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()
答案 1 :(得分:2)
如果您想读取和修改共享数据,请在两个分别运行的脚本之间进行操作,一个好的解决方案是利用python多处理模块,并使用Pipe() or a 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")
编辑:刚刚发现您可以使用queue.get(False)来避免在接收数据时出现阻塞。这样,无需先检查队列是否为空。如果使用管道,则不可能。
答案 2 :(得分:0)
您可以使用pickling模块在两个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()