【问题标题】:ValueError: I/O operation on closed csv fileValueError:对已关闭的 csv 文件的 I/O 操作
【发布时间】:2018-12-18 04:23:44
【问题描述】:

即使在正确缩进之后,以下代码也会显示已关闭文件的 I/O 错误。错误可能来自哪里?请检查函数调用,我是初学者,也可能有错误。

from tkinter import *
from tkinter import ttk
import csv

win= Tk()
win.resizable(0, 0)
win.title('ADD PRODUCT')

global text_input
global int_input1
global int_input2
global int_input3
global int_input4

text_input=StringVar()
int_input1=IntVar()
int_input2=IntVar()
int_input3=IntVar()
int_input4=IntVar()

with open('products_database.csv', 'w', newline='') as x:
        fieldnames=('Barcode', 'item', 'sales_price', 'purchase_price',    'reorder_level')
        writer=csv.DictWriter(x, fieldnames=fieldnames)
        writer.writeheader()

        def saver():
                with open('products_database.csv', 'a', newline='') as y:
                        writer.writerow({'Barcode':int_input1.get(), 'item':text_input.get(),'sales_price':int_input2.get(),'purchase_price':int_input3.get(), 'reorder_level':int_input4.get()})
                        y.close()

def clear():
        operator=text_input.set('')
        operator=int_input1.set('')
        operator=int_input2.set('')
        operator=int_input3.set('')
        operator=int_input4.set('')

a=Label(win, text='Scan barcode').grid(column=0, row=0)
b=Entry(win, text=int_input1).grid(column=1, row=0)
c=Label(win, text='Item').grid(column=0, row=1)
d=Entry(win, text=text_input).grid(column=1, row=1)
e=Label(win, text='Sale price').grid(column=0, row=2)
f=Entry(win, text=int_input2).grid(column=1, row=2)
h=Label(win, text='Purchase price').grid(column=0, row=3)
i=Entry(win, text=int_input3).grid(column=1, row=3)
j=Label(win, text='Reorder level').grid(column=0, row=4)
k=Entry(win, text=int_input4).grid(column=1, row=4)
l=Button(win, text='Clear', width=20, command=clear).grid(column=0, row=5,    columnspan=1)
m=Button(win, text='Save', width=20, command=saver).grid(column=1, row=5)

【问题讨论】:

  • 为什么要在with 语句中定义一个函数?为什么要在 with 语句的末尾关闭文件?
  • 您好,我了解文件关闭。但是我在 with 语句中放置了一个函数,以便我可以在其中一个按钮中将其作为命令调用。调用整个 with 语句会导致在整个 csv 文档中写入标题。我需要程序编写一次标题,然后在每次调用时附加行。
  • 你能推荐更好的代码/语法吗?

标签: python-3.x csv io


【解决方案1】:

当您定义一个使用其外部范围内的变量的函数时,它将保留对这些变量的引用,以便在您调用它时可以使用它们,但是当您使用with 语句时,文件会在您退出时关闭,因此当您调用 saver x 时,您将尝试使用 writer,它使用 x,但它失败了。尝试在保存标头的部分之外定义 saver 函数并像这样制作自己的 csv 编写器:

from tkinter import *
from tkinter import ttk
import csv

win= Tk()
win.resizable(0, 0)
win.title('ADD PRODUCT')

global text_input
global int_input1
global int_input2
global int_input3
global int_input4

text_input=StringVar()
int_input1=IntVar()
int_input2=IntVar()
int_input3=IntVar()
int_input4=IntVar()

with open('products_database.csv', 'w') as x:
    fieldnames=('Barcode', 'item', 'sales_price', 'purchase_price',  'reorder_level')
    writer=csv.DictWriter(x, fieldnames=fieldnames)
    writer.writeheader()

def saver():
    with open('products_database.csv', 'a') as y:
        writer=csv.DictWriter(y, fieldnames=fieldnames)
        writer.writerow({'Barcode':int_input1.get(), 'item':text_input.get(),'sales_price':int_input2.get(),'purchase_price':int_input3.get(), 'reorder_level':int_input4.get()})

def clear():
    operator=text_input.set('')
    operator=int_input1.set('')
    operator=int_input2.set('')
    operator=int_input3.set('')
    operator=int_input4.set('')

a=Label(win, text='Scan barcode').grid(column=0, row=0)
b=Entry(win, text=int_input1).grid(column=1, row=0)
c=Label(win, text='Item').grid(column=0, row=1)
d=Entry(win, text=text_input).grid(column=1, row=1)
e=Label(win, text='Sale price').grid(column=0, row=2)
f=Entry(win, text=int_input2).grid(column=1, row=2)
h=Label(win, text='Purchase price').grid(column=0, row=3)
i=Entry(win, text=int_input3).grid(column=1, row=3)
j=Label(win, text='Reorder level').grid(column=0, row=4)
k=Entry(win, text=int_input4).grid(column=1, row=4)
l=Button(win, text='Clear', width=20, command=clear).grid(column=0, row=5,  columnspan=1)
m=Button(win, text='Save', width=20, command=saver).grid(column=1, row=5)

您也不需要调用y.close(),因为它在with 语句中(虽然这不是错误的来源,但文件可以关闭任意次数,但实际上只有第一个效果)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-27
    • 2016-07-21
    • 2015-07-20
    • 1970-01-01
    • 2016-08-26
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多