【问题标题】:Running Psychopy window from a thread segfaults从线程段错误运行 Psychopy 窗口
【发布时间】:2015-06-11 11:08:49
【问题描述】:

我正在尝试从一个单独的线程运行我的 Psychopy 窗口并从另一个线程控制其上显示的内容,但我得到的只是致命的 Python 错误。

这是一个小示例脚本,它产生的结果与我的大脚本相同

from threading import Thread
from psychopy import visual, core
import time

class ThreadTest(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.text='Test'
        self.running = 1
        self.start()
        print 'doing stuff'

    def run(self):
        win = visual.Window()

        msg = visual.TextStim(win, text=self.text)
        while self.running:
            msg.setText(self.text)
            msg.draw()
            win.flip()
            print 'Drawing...'
            core.wait(2)

        win.close()
        print 'Stopping thread'

    def setText(self, text):
        self.text=text

    def stopTest(self):
        self.running = 0


def main():
    tt = ThreadTest()
    time.sleep(3)
    tt.setText('Test2')
    time.sleep(3)
    tt.stopTest()
    print 'Stopping main thread'

if __name__ == '__main__':
    main()

和输出

python testy.py 
doing stuff
Fatal Python error: (pygame parachute) Segmentation Fault
Aborted (core dumped)

这会创建 Psychopy 窗口,但无法在其上显示任何文本,然后就崩溃了。我也尝试在__init__() 中创建窗口,但这也不起作用。

【问题讨论】:

  • 看来问题出在 TextStim 上,因为当我将 msg = visual.TextStim(win, text=self.text) 更改为 msg = visual.Rect(win) 并删除 msg.setText(self.text) 时,程序正常工作。差不多了,当程序关闭时它仍然崩溃。
  • 另外,如果我在 __init__ 中初始化 TextStim 然后不调用 msg.setText() 程序在停止之前不会崩溃,但是 Psychopy 窗口中没有显示文本。如果我尝试更改线程中的文本,程序会崩溃。

标签: multithreading psychopy


【解决方案1】:

这似乎是文本对象的问题,它来自 pyglet,可能会干扰 pyglet 线程。下面的代码确实有效(令我惊讶)!

但是您正在做一些强烈反对且不受支持的事情。 OpenGL 调用(处理所有渲染)不是线程安全的,不应从主线程以外的任何地方调用。

基本上,您从这里开始就靠自己了! ;-)

from threading import Thread
from psychopy import visual, core
import time

class ThreadTest(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.ori=0
        self.running = 1
        print 'initialised'

    def run(self):
        win = visual.Window()
        print 'created window'
        stim = visual.PatchStim(win)
        print 'created stim'
        while self.running:
            stim.ori = self.ori
            stim.draw()
            win.flip()
            print '.',
            core.wait(0.01)

        print 'Stopping auxil thread'

    def setOri(self, ori):
        self.ori=ori

    def stopTest(self):
        self.running = 0


def main():
    tt = ThreadTest()
    tt.start()
    for frameN in range(180):
        tt.setOri(frameN)
        time.sleep(0.01)
    tt.stopTest()
    print 'Stopping main thread'

if __name__ == '__main__':
    main()

【讨论】:

  • 感谢您的回答。 TextStim 真的不想出现在主循环之外的任何地方。
【解决方案2】:

罪魁祸首确实是不在主循环中的 TextStim。当我交换 main 和 drawloops 时,它开始工作。现在我只需要找到一种方法来停止新线程,即使它正在做某事。

from threading import Thread
from psychopy import visual, core
import time

class ThreadTest(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.text='Test'
        self.running = 1

        print 'doing stuff'

    def run(self):
        time.sleep(3)
        self.setText('Test2')
        time.sleep(3)
        self.stopTest()

    def mainloop(self):
        win = visual.Window()
        while self.running:

            msg = visual.TextStim(win)
            msg.setText(self.text)
            msg.draw()
            win.flip()
            print 'Drawing...'
            core.wait(2)
        win.close()
        print 'Stopping thread'

    def setText(self, text):
        self.text=text

    def stopTest(self):
        self.running = 0


def main():
    tt = ThreadTest()
    tt.start()
    tt.mainloop()
    print 'Stopping main thread'

if __name__ == '__main__':
    main()

【讨论】:

  • 您现在在每次屏幕刷新时都创建一个新的文本对象,这是非常低效的。所有这一切都远非理想,所以我希望刺激时机对你来说并不重要
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-24
  • 1970-01-01
相关资源
最近更新 更多