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

Jor*_*son 6 python tkinter python-2.7

如果我运行了一个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)
Run Code Online (Sandbox Code Playgroud)

脚本B

import time
from scriptA import return_data

if __name__ == '__main__':
    while True:
        print return_data()  # from script A
        time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

Aks*_*pte 11

您可以使用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"
Run Code Online (Sandbox Code Playgroud)

mp1.py:

from multiprocessing import Process,Pipe

def f(child_conn):
    msg = "Hello"
    child_conn.send(msg)
    child_conn.close()
Run Code Online (Sandbox Code Playgroud)


ono*_*ila 10

如果您想在 2 个单独运行的脚本之间读取和修改共享数据,一个好的解决方案是,利用 python 多处理模块,并使用Pipe() 或 Queue()(请参阅此处的差异)。这样,您就可以同步脚本,并避免有关并发性和全局变量的问题(例如,如果两个脚本都想同时修改变量会发生什么情况)。

正如 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
Run Code Online (Sandbox Code Playgroud)
    # 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')
Run Code Online (Sandbox Code Playgroud)
    # 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")             
Run Code Online (Sandbox Code Playgroud)

编辑:刚刚发现您可以使用queue.get(False)来避免接收数据时的阻塞。这样就不需要先检查队列是否为空。如果您使用管道,这是不可能的。