You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

每次运行代码创建含日期时间的新CSV文件时提示文件不存在的问题

问题分析与修复

核心错误点

  1. 文件名包含非法字符:Windows系统下文件名不能包含:,你用%H:%M:%S生成的时间带冒号,导致无法创建文件。
  2. 文件提前关闭:with open(title, 'w') as data:语句执行完后,文件会被自动关闭,后续循环里再调用writer = csv.writer(data)会报错,因为文件句柄已失效。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 03:42:35