我一直在开发PsychoPy编码器部分的实验。这是一项相对简单的任务,但需要大量的文本和图像绘制。我几天前试过运行整个实验(包括123次试验),并且在第28次迭代中我收到了以下错误:
WindowsError:exception:写入0x00000004的访问冲突
我调查了这一点,看起来在向窗口绘制大量文本时会出现pyglet中导致的内存泄漏问题。我将我的代码改进为仅在实验需要时更改文本组件。我在下面列出了我的整个代码作为参考:
from __future__ import division
from psychopy import locale_setup, visual, core, event, data, gui
import numpy as np
import pandas as pd
import sys, os, csv, time, random
from win32api import GetSystemMetrics
#Directory:
cwd = os.path.dirname(os.path.abspath(__file__))
#GUI:
expName = "CMNT"
expInfo = {"participant": "", "session": "001", "condition": "F1"} #Condition Files: F1, F2, M1, or M2
condition = expInfo["condition"]
condition = expInfo["condition"]
dlg = gui.DlgFromDict(dictionary = expInfo, title = expName, order = ["participant","session","condition"])
if dlg.OK == False:
core.quit()
#Window:
win = visual.Window(size = (GetSystemMetrics(0), GetSystemMetrics(1)), fullscr = True, pos = (0,0), units = "norm", color = "Gray")
#Turn off Mouse
event.Mouse(visible = False)
#Timers:
timer = core.Clock()
breakTimer = core.Clock()
#Load Condition File:
stim_df = pd.read_csv("exp_stimuli.csv", nrows = 124)
run_length = 123
#Output Directory:
fileLocation = cwd + "\%s_data\%s" %(expName, expInfo["participant"])
if not os.path.exists(fileLocation):
os.makedirs(fileLocation)
os.chdir(fileLocation)
if os.path.isfile("logFile.csv"):
os.remove("logFile.csv")
#List and Panda File Header
run_param_list = []
header = ["Block","MentalState", "Condition", "Speaker","Prompt", "RespButton", "CorrAnswer","RT(sec)", "ACC"]
#Define text and image stimuli
text = visual.TextStim(win = win, text = '', height = 0.1, pos = (0,0), color="White")
image = visual.ImageStim(win = win, pos = (0,0), size = (0.1,0.1), image = cwd + "\\" + "gray.png")
#Run Instruction Page:
text.text = '\t\tREMEMBER:\n\t\tAnswer each question,\n\t\t"Which should I pick?"\n\t\tusing the LEFT and RIGHT\n\t\tarrow key.'
text.height = 0.1
text.draw()
win.flip()
while True:
theseKeys = event.getKeys()
if "escape" in theseKeys:
core.quit()
if len(theseKeys):
break
#Begin Trials:
for i in xrange(run_length):
if stim_df["MentalState"][i] == "0":
breakTimer.reset()
while breakTimer.getTime() < 15.0:
text.text = "+"
text.height = 0.25
text.pos = (0,0)
text.draw()
win.flip()
else:
#win.flip()
timer.reset()
exit_press = []
event_press = []
speaker = visual.TextStim(win, text = stim_df["speaker"][i], height = 0.1, pos = (0,0.6))
speaker.setAutoDraw(True)
#0.5 seconds
while timer.getTime() < 0.5:
win.flip()
#3.0 seconds
if stim_df["speaker"][i] == "Computer":
text.text = stim_df["prompt"][i]
text.pos = (-0.1,0)
text.height = 0.08
text_box_length = text.boundingBox[0]/GetSystemMetrics(0)*2
image.image = cwd + "\\" + "gray.png"
image.pos = (-0.1,0)
image.size = (text_box_length, 0.35)
image.draw()
text.draw()
else:
text.text = stim_df["prompt"][i]
text.pos = (-0.1,0)
text.height = 0.08
text_box_length = text.boundingBox[0]/GetSystemMetrics(0)*2
image.image = cwd + "\\" + "blue.png"
image.pos = (-0.1,0)
image.size = (text_box_length, 0.35)
image.draw()
text.draw()
win.flip()
while timer.getTime() < 3.5:
exit_press += event.getKeys()
if "escape" in exit_press:
core.quit()
onset_Time = timer.getTime()
speaker.setAutoDraw(False)
#3.5 seconds
text.text = stim_df["question"][i]
text.pos = (0,0.6)
text.height = 0.1
text.draw()
text.text = stim_df["answerA"][i]
text.pos = (-0.3, -0.5)
text.draw()
text.text = stim_df["answerB"][i]
text.pos = (0.3, -0.5)
text.height = 0.1
text.draw()
win.flip()
length = 0
while timer.getTime() < 7.0:
event_press += event.getKeys(keyList = ["left","right"])
if len(event_press) > length:
RT = timer.getTime() - onset_Time
length = len(event_press)
elif len(event_press) == 0:
RT = "N/A"
exit_press += event.getKeys()
if "escape" in exit_press:
core.quit()
#Jitter 1 time
text.text = "+"
text.pos = (0,0)
text.height = 0.25
text.draw()
win.flip()
while timer.getTime() < 7.0 + (stim_df["jitter1"][i]/1000):
exit_press += event.getKeys()
if "escape" in exit_press:
core.quit()
#Check Conditional Input
try:
response = event_press[-1]
except:
response = None
if response == "left":
reply = stim_df["answerA"][i]
if reply == stim_df["corrAnswer"][i]:
acc = 1
else:
acc = 0
elif response == "right":
reply = stim_df["answerB"][i]
if reply == stim_df["corrAnswer"][i]:
acc = 1
else:
acc = 0
elif response == None:
response = "N/A"
reply = stim_df["corrAnswer"][i]
acc = 0
text.text = reply
text.height = 0.08
text.pos = (0.1,0.3)
#2 seconds
if stim_df["speaker"][i] == "Computer":
text.text = reply
text.height = 0.08
text.pos = (0.1,0.3)
speaker.draw()
image.image = cwd + "\\" + "gray.png"
image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.2, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1)
image.pos = (0.1, 0.3)
image.draw()
text.draw()
text.pos = (-0.1,-0.1)
text.text = reply + u" \u2713"
text_box_length = text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1
image.image = cwd + "\\" + "gray.png"
image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1)
image.pos = (-0.1,-0.1)
image.draw()
text.draw()
else:
text.text = reply
text.height = 0.08
text.pos = (0.1,0.3)
speaker.draw()
image.image = cwd + "\\" + "green.png"
image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1)
image.pos = (0.1,0.3)
image.draw()
text.draw()
text.text = reply + " :)"
text.pos = (-0.1,-0.1)
image.image = cwd + "\\" + "blue.png"
image.size = (text.boundingBox[0]/GetSystemMetrics(0)*2 + 0.1, text.boundingBox[1]/GetSystemMetrics(1)*2 + 0.1)
image.pos = (-0.1, -0.1)
image.draw()
text.draw()
win.flip()
while timer.getTime() < 9.0 + (stim_df["jitter1"][i]/1000):
exit_press += event.getKeys()
if "escape" in exit_press:
core.quit()
#Jitter 2 time
text.text = "+"
text.height = 0.25
text.pos = (0,0)
text.draw()
win.flip()
while timer.getTime() < 11.0 + (stim_df["jitter1"][i]/1000) + (stim_df["jitter2"][i]/1000):
exit_press += event.getKeys()
if "escape" in exit_press:
core.quit()
#Panda Output File
run_param_list.append([stim_df["block"][i], stim_df["MentalState"][i], condition, stim_df["speaker"][i], stim_df["prompt"][i], response, stim_df["corrAnswer"][i], RT, acc])
fid = pd.DataFrame(run_param_list, columns = header)
fid.to_csv("logFile.csv", header = True)
#Close up Shop:
win.close()
core.quit()
我想知道是否有人建议如何更好地优化代码,以免发生内存泄漏错误。如果无法修复此错误,最佳解决方案是通过PsychoPy Builder复制实验吗?
答案 0 :(得分:1)
我的猜测是,这来自pyglet中似乎存在的内存泄漏(这是我们用于文本呈现的内容): https://bitbucket.org/pyglet/pyglet/issues/66/memory-leak-in-fonttext 听起来像其中一个pyglet开发人员已经找到了解决方案,但是不会包含一段时间。
PsychoPy还有一个名为TextBox的刺激类。这完全是从头开始编写的(由Sol Simpson编写)并且在许多方面更有效,但不能很好地支持字体(具体来说,目前仅支持单倍间距字体)。如果你能够使用它,我相信不会显示相同的内存问题。