2

私が今抱えている酸洗いエラーに対して、誰かが良い解決策を持っているかどうか疑問に思いました。いくつかの異なるプロセスを並行して開くようにコードを設定しようとしています。各プロセスには、matplotlibキャンバスにリアルタイムで表示されるフィッティングプロセスがあります。メインアプリケーション内に、この機能をアクティブにするボタンがあります。

def process_data(self):
        process_list = []
        for tab in self.tab_list:
            process_list.append(mp.Process(target=process_and_fit, args=(tab,)))
            process_list[-1].start()
            process_list[-1].join()
        return

お気づきかもしれませんが、「タブ」(PyQt4.QtGui.QTabWidgetオブジェクト)が関数process_and_fitに渡されますが、これは簡単に選択できないことに気づきました(ここにリンク)。ただし、渡されるフレームを削除するためにコードを変更する方法はわかりません。これは、process_and_fit関数で間接的に呼び出す必要があるためです。間接的に私はこのようなものを意味します:(再び疑似コード)

def process_and_fit(tab): # this just sets up and starts the fitting process
        result = lmfit.Minimizer(residual, parameters, fcn_args=(tab,))
        result.prepare_fit()
        result.leastsq()

def residual(params, tab):
    residual_array = Y - model
    tab.refreshFigure()
    return residual_array

class tab(QtGui.QTabWidget):
    def __init__(self, parent, spectra):
       # stuff to initialize the tab widget and hold all of the matplotlib lines and canvases

    # This just refreshes the GUI stuff everytime that the parameters are fit in the least squares method
    def refreshFigure(self):     
        self.line.set_data(self.spectra.X, self.spectra.model)
        self.plot.draw_artist(self.line)
        self.plot.figure.canvas.blit(self.plot.bbox)

プロセスに関連付けられたタブには1セットのデータのみが関連付けられている必要があるため、このピクルスエラーを回避する方法を知っている人はいますか?Steven Bethardのアプローチを見ましたが、コードをどこに置くか、どのように利用するかが本当にわかりませんでした。(私は化学技術者であり、コンピューター科学者ではないので、理解できないことがたくさんあります)

どんな助けでも大歓迎です。

編集:要求に応じて、忘れたリンクを追加しました。

4

1 に答える 1

2

主な問題は、メインUIスレッド(すべてのQt呼び出しが含まれているプロセス)とは別のプロセスからUIを変更できないことです。mp.Pipeまたはmp.Queueを使用して、メインプロセスに通信する必要があります。

def process_data(self):
    for tab in self.tab_list:
        consumer, producer = mp.Pipe()
        process_list.append(mp.Process(target=process_and_fit, args=(producer,)))
        process_list[-1].start()
        while (true):
            message = consumer.recv()  # blocks
            if message == 'done':
                break
            # tab.spectra.X, tab.spectra.model = message
            tab.refreshFigure()
        process_list[-1].join()
    return

def process_and_fit(pipe_conn):
    ...
    pipe_conn.send('done')

def residual(params, pipe_conn):
    residual_array = Y - model
    pipe_conn.send('refresh')  # or replace 'refresh' with (X, model)
    return residual_array

もう1つ注意すべき点は、をブロックするconsumer.recv()とGUIスレッドがハングする可能性があるということです。これを軽減するためのリソースはたくさんあります。おそらくsに切り替える必要があるため、「PopenブロッキングPyQtGUIのサブプロセスQThread」という質問が役立ちます。(Qthread:PySidePyQt

Pythonスレッドの代わりにQThreadsを使用する利点は、QThreadsを使用すると、すでにQtのメインイベントループに入っているため、非同期(非ブロッキング)コールバックを使用してUIを更新できることです。

于 2013-02-06T19:14:46.297 に答える