在Python脚本之间传递数据,同时单独运行

时间:2017-05-09 04:30:31

标签: python python-2.7 tkinter

如果我运行了一个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)

3 个答案:

答案 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()