Интеграция двух программ обработки событий в Python

У меня есть две программы на Python. Назовем их Prog1.py и Prog2.py. Prog1 помогает мне получать оперативные данные с внешнего устройства. На данный момент, как и когда он получает данные, он печатает их на экране. Существует цикл while, в котором на каждой итерации он распечатывает новый набор полученных данных. Теперь Prog2 — это программа Python, созданная с использованием PyQtGraph, которая предназначена для отображения данных в реальном времени, как на мониторе. На данный момент то, что делает Prog2, это то, что (то есть, когда он запускается отдельно), он отображает уже полученные данные. Это движущийся сюжет. Таким образом, Prog2.py имеет функцию обновления, которая повторно вызывается таймером через определенные промежутки времени, чтобы обновить график следующей точкой данных (чтобы заставить его двигаться вправо). Моя цель состоит в том, чтобы связать Prog1 и Prog2 - то есть каким-то образом я хочу передать данные, полученные Prog1 в режиме реального времени, в Prog2, чтобы Prog2 мог отображать данные в реальном времени.

Поскольку Prog1 и Prog2 являются независимыми событиями, имеющими собственный цикл обработки событий, я не знаю, как их связать. Я думал, что одна наивная идея состояла в том, чтобы запустить Prog1.py и Prog2.py параллельно и попросить Prog1.py сохранить данные в файл (может быть, замариновать их?), а затем попросить Prog2.py прочитать из него, а затем построить график. Но меня это не убеждает. Это выглядит грязно. Каким-то образом я хочу запустить весь код Prog2.py внутри Prog1.py. Есть ли чистый способ сделать это?

РЕДАКТИРОВАТЬ- Код

Prog1.py

/*

Code to get data from USB

*/

def main():
    while 1:
        data = get_data()
        print data

main()

Prog2.py — это код PyQtGraph через таймер для обновления графика и его прокрутки.


person user1955184    schedule 20.06.2014    source источник
comment
Вероятно, вы могли бы добиться этого с помощью потоковой обработки. Пусть один поток выполняет всю тяжелую работу с оперативными данными, а другой поток занимается построением графика. Дайте второму потоку событие, которое обновит график, и когда первый поток захватит данные, это событие сработает. Это если вы хотите, чтобы все это было в одной программе, как вы сказали. См. docs.python.org/2/library/threading.html#event. -объекты   -  person Bob    schedule 20.06.2014
comment
Мне также удалось объединить библиотеку (Live555), которая имеет собственный цикл обработки событий, с моим графическим интерфейсом Qt. Вы можете легко добиться этого с помощью потоков, если соблюдаете основные правила потоков.   -  person Murat Şeker    schedule 20.06.2014


Ответы (1)


У вас есть несколько вариантов, возможно, любой из них будет работать:

  1. Объедините программы в одну с рабочим потоком, который отслеживает данные и отправляет их обратно в основной поток для построения графика. (см.: https://groups.google.com/forum/#!msg/pyqtgraph/haiJsGhxTaQ/RkOov_UZEcYJ)
  2. Объедините программы в однопоточную программу с таймером, который проверяет наличие новых данных и повторяет график всякий раз, когда данные поступают:

    plt = pg.plot()
    def update():
        data = getNewData()
        if data is not None:
            plt.plot(data, clear=True)
    timer = QTimer()
    timer.timeout.connect(update)
    timer.start(10)
    
  3. Держите программы раздельными и используйте какую-либо форму IPC — сокеты, каналы и т. д. для связи между ними. Это потребует сериализации данных (возможно, с помощью pickle, как вы предлагаете). pyqtgraph.multiprocess даже позволяет отправлять сигналы Qt между процессами. Это, наверное, самый сложный вариант, но вот простой пример:

    import pyqtgraph as pg
    import pyqtgraph.multiprocess as mp
    proc = mp.QtProcess() # start second process for plotting
    rpg = proc._import('pyqtgraph') 
    plt = rpg.plot() # create a PlotWidget in remote process
    
    # Unlike the last example, we can use a wile-loop here because the Qt
    # event loop is running in another process.
    while True:
        data = getNewData()
        if data is not None:
            plt.plot(data, clear=True, _callSync='off')
    
person Luke    schedule 21.06.2014
comment
В вашем втором предложении getNewData() - это мой Prog1.py, который получает с частотой 128 (я получаю 128 точек данных в секунду). Он имеет отдельный цикл, который печатает данные по мере их поступления. Ваш код предлагает вызывать getNewData только с промежутком в 10 мс? Извините, но не могли бы вы уточнить немного больше? Я отредактировал свой пост для большей ясности. - person user1955184; 23.06.2014
comment
Конечно, вы можете запускать таймер с любым интервалом, который вам нравится. Работает ли какое-либо из этих предложений для вас, будет зависеть от деталей вашего сбора данных (например, требуется ли вам опрашивать устройство с некоторым максимальным интервалом? Как долго вы можете ждать, прежде чем данные будут удалены?) и от производительности ваша система в рисовании данных. Использовать таймеры (2) проще всего, но если вы обнаружите, что рисование вызывает неприемлемо большие задержки в сборе данных, тогда более подходящим может быть параллельный метод (1 или 3). - person Luke; 23.06.2014