每次运行代码创建含日期时间的新CSV文件时提示文件不存在的问题
问题分析与修复
核心错误点
- 文件名包含非法字符:Windows系统下文件名不能包含
:,你用%H:%M:%S生成的时间带冒号,导致无法创建文件。 - 文件提前关闭:
with open(title, 'w') as data:语句执行完后,文件会被自动关闭,后续循环里再调用writer = csv.writer(data)会报错,因为文件句柄已失效。 - Summary文件处理不规范:未使用上下文管理器管理文件,存在资源泄漏风险。
修复后的代码
import pygame import csv import time from datetime import datetime # Initialize pygame starts pygame.init() # Set the dimensions of the screen screen_width = 1275 screen_height = 750 # Set the colors white = (255, 255, 255) black = (0, 0, 0) # Set the font font = pygame.font.SysFont('Arial', 20) # Set the button properties button_radius = 70 button_x_spacing = 400 button_y_spacing = 200 # Set the button positions button_positions = [ (button_x_spacing, button_y_spacing), (button_x_spacing, button_y_spacing + 200), (button_x_spacing, button_y_spacing + 400) ] # Initialize the screen screen = pygame.display.set_mode((screen_width, screen_height)) # Set the caption pygame.display.set_caption("Marmoset Buttons") # Set the clock clock = pygame.time.Clock() # Set the counters button0click = 0 button1click = 0 button2click = 0 clickoutsidebutton = 0 trialnum = 0 # Psuedorandom sequence of numbers sequence = [1,1,2,2,1,2,1,0,1,1, 1,2,1,0,1,0,1,2,1,1, 2,1,0,1,2,1,1,0,1,2, 2,1,0,2,1,1,1,0,1,1, 1,1,0,1,1,1,2,0,2,1, 2,1,0,1,0,1,1,2,2,1, 1,0,1,1,0,0,1,1,2,2, 1,1,2,1,1,2,1,0,1,1, 1,1,1,0,1,1,2,0,2,1, 0,1,1,2,1,0,1,2,1,0, 1,1,0,1,1,2,1,2,1,0, 2,1,2,1,1,2,1,1,0,1, 1,0,1,1,0,1,1,1,1,1, 1,1,2,1,1,1,0,1,1,2, 1,2,1,0,1,2,2,2,1,0, 1,2,1,0,0,1,2,1,2,0, 1,0,1,1,1,0,1,1,2,1, 0,1,2,2,1,1,1,0,1,1, 1,0,1,2,0,1,0,1,1,2, 0,1,2,1,2,1,2,2,1,0, 1,1,1,0,1,1,0,1,1,0, 1,2,2,1,0,1,1,2,0,1, 1,0,1,2,1,0,1,2,1,0, 1,0,1,1,2,2,1,1,0,0, 1,2,1,2,1,1,1,0,1,0, 1,1,0,1,2,1,1,2,1,0, 1,2,1,1,0,1,0,1,1,0, 1,2,0,2,1,2,1,0,0,1, 1,1,1,1,0,0,1,2,0,1, 0,1,2,0,1,2,1,2,1,0, 1,0,1,2,1,1,2,0,1,2, 0,0,1,0,2,1,2,1,2,1, 1,2,2,2,1,1,2,1,1,0, 1,2,1,1,0,2,1,2,1,1, 1,2,2,1,1,2,1,0,0,1, 2,1,2,1,0,2,1,2,0,0, 1,0,1,1,2,2,1,0,1,0, 0,1,2,1,1,0,1,2,0,1, 1,0,0,1,2,1,2,1,0,0, 1,2,0,0,2,1,0,2,1,1, 1,1,1,1,2,1,1,0,1,1, 2,1,0,1,1,0,1,2,1,0, 0,1,2,1,2,1,0,1,2,1, 2,1,0,2,1,2,1,1,2,1, 1,1,0,1,1,1,2,1,1,1, 2,1,2,1,0,0,1,2,1,2, 1,0,1,2,1,2,0,1,2,2, 2,0,1,2,1,2,1,0,1,1, 1,2,1,0,1,2,0,2,2,2, 1,2,2,1,1,0,1,1,0,0, 1,1,0,1,0,0,1,2,1,2, 1,0,2,1,2,1,2,1,0,1, 1,2,1,1,0,1,1,0,0,1, 1,1,1,2,1,1,0,1,1,1, 1,2,1,0,2,2,1,2,0,1, 1,1,2,2,1,0,1,2,1,0, 1,2,0,1,1,0,1,1,2,1, 1,2,2,2,1,1,1,0,1,0, 1,2,0,0,0,1,2,2,0,1, 0,2,1,0,0,1,2,2,2,1, 1,1,2,1,0,1,0,1,2,1, 1,2,1,0,1,1,2,1,0,2, 1,0,2,2,1,0,1,0,2,1, 1,0,2,1,2,1,1,0,0,1, 1,2,1,2,1,1,1,0,1,1, 1,1,0,0,1,2,1,2,1,0, 1,2,1,2,2,1,0,1,0,0, 2,1,0,2,0,1,0,1,2,1, 1,1,0,1,0,1,1,1,0,1, 1,2,1,0,1,0,1,2,1,0, 2,1,2,2,1,0,1,0,1,1, 2,1,2,0,1,2,1,2,0,0, 1,1,2,0,2,1,2,1,1,0, 1,2,1,0,0,1,1,2,1,2, 1,2,2,1,1,1,1,2,0,0, 1,2,1,0,0,2,1,0,2,1, 1,0,1,1,2,1,2,0,1,2, 2,1,0,1,1,0,1,2,1,0, 0,1,0,1,2,1,1,2,1,0, 2,2,1,0,0,1,2,1,2,1] # Truncating list trials = int(input("Number of trials: ")) n = len(sequence) for i in range(0, n - trials): sequence.pop() AnimalName = input("Animal Name: ") StepName = input("Step: ") thedatetime = datetime.now() date = thedatetime.date() # 替换时间中的冒号为连字符,避免Windows文件名非法字符 thetime = thedatetime.strftime("%H-%M-%S") title = AnimalName + "_S" + StepName + "_" + str(date) + "_" + str(thetime) + ".csv" # 添加.csv后缀更规范 # 把主数据文件的打开放在循环外面,用with包裹整个流程,确保文件持续打开 with open(title, 'w', newline='') as data, open("Summary.csv", 'w', newline='') as data2: writer = csv.writer(data) writer.writerow(["Trial#", "Event Code", "Time"]) writer2 = csv.writer(data2) writer2.writerow(["Trial#", "Button 0 Clicks", "Button 1 Clicks", "Button 2 Clicks", "Outside Clicked", "Time"]) # For loop parsing through sequence for i in sequence: trialnum += 1 if trialnum%10 == 0: writer2.writerow([trialnum, button0click, button1click, button2click, clickoutsidebutton, time.asctime(time.localtime(time.time()))]) # Delay between buttons screen.fill(black) pygame.display.update() pygame.time.delay(500) # While loop variable button_clicked = False # Starts Timer start_time = pygame.time.get_ticks() timenow = time.time() writer.writerow([trialnum, i, time.asctime(time.localtime(time.time()))]) # Loops while button isn't clicked while not button_clicked: # Time out for 15 seconds seconds = (pygame.time.get_ticks() - start_time)/1000 # 用>=避免因为帧率问题错过等于15的时机 if seconds >= 15: timenow = time.time() writer.writerow([trialnum, 4, time.asctime(time.localtime(time.time()))]) break # Checks when screen is touched for event in pygame.event.get(): if event.type == pygame.MOUSEBUTTONDOWN: # Distance between point touched and button distance_button = pygame.math.Vector2(button_positions[i]) - pygame.math.Vector2(pygame.mouse.get_pos()) # Checks if distance is within button if distance_button.length() < button_radius: button_clicked = True timenow = time.time() writer.writerow([trialnum, 150, time.asctime(time.localtime(time.time()))]) # Counts which buttons were pressed if i == 0: button0click += 1 elif i == 1: button1click += 1 elif i == 2: button2click += 1 # Counts when click was outside of button else: clickoutsidebutton += 1 x = pygame.mouse.get_pos()[0] if x <= 425: timenow = time.time() writer.writerow([trialnum, 201, time.asctime(time.localtime(time.time()))]) elif x <= 850: timenow = time.time() writer.writerow([trialnum, 200, time.asctime(time.localtime(time.time()))]) elif x > 850: timenow = time.time() writer.writerow([trialnum, 202, time.asctime(time.localtime(time.time()))]) # Draws the button pygame.draw.circle(screen, white, button_positions[i], button_radius) text_surface = font.render(f"Button {i}", True, black) text_rect = text_surface.get_rect(center=button_positions[i]) screen.blit(text_surface, text_rect) pygame.display.update() # Printing results print("Button 0 was clicked: " + str(button0click) + " times.") print("Button 1 was clicked: " + str(button1click) + " times.") print("Button 2 was clicked: " + str(button2click) + " times.") print("The area around the button was clicked: " + str(clickoutsidebutton) + " times.")
关键修复说明
- 文件名处理:将时间格式中的
:替换为-,并添加.csv后缀,符合文件命名规范。 - 文件生命周期管理:用一个
with语句同时打开主数据文件和Summary文件,确保在整个程序运行期间文件处于打开状态,避免句柄失效问题。 - 超时判断优化:将
seconds == 15改为seconds >= 15,避免因为pygame帧率问题错过精确的15秒节点。 - 简化Summary逻辑:提前初始化Summary的writer,无需在trialnum==10时单独处理,代码更简洁。
内容的提问来源于stack exchange,提问作者user22019679
相关产品推荐
相关产品推荐

