首页 > 解决方案 > 在类或函数中保持文件打开以进行写入

问题描述

我正在尝试编写将类变量写入 .csv 文件的代码,只要创建了该类的对象。我目前的代码是:

class planet():
def __init__(self, constant, parent, angle, tier):
    global csv_file
    self.writer = csv.DictWriter(csv_file, fieldnames = ["Name", "Constant", "Height", "Period", "Tier", "Parent", "Size"])
    self.writer.writerow({"Name": "Bob", "Constant": str(self.constant), "Height": str(self.height), "Period": str(self.period), "Tier": str(self.tier), "Parent": "Jeff", "Size": str(self.size)})

PS(抱歉格式化,我无法让包装看起来不错)

为了清楚起见,init() 函数中的其他行已被删除,因为它们不会影响我的这部分代码。在代码的前面,我调用了这个函数来打开我的 .csv 文件:

def export():
global csv_file
with open('Solar System.csv', mode='w') as csv_file:
    writer = csv.DictWriter(csv_file, fieldnames = ["Name", "Constant", "Height", "Period", "Tier", "Parent", "Size"])
    writer.writeheader()

当我尝试这段代码时,我得到了这个错误:ValueError: I/O operation on closed file。我知道这是因为我正在尝试写入已关闭的文件。为了解决这个问题,我尝试将with open()语句放在我的顶部,__init__()但这不起作用,因为每当调用该类时,它都会删除前一行并用自己的数据编写它。

为了澄清我的问题是:

  1. 如何对此进行排序,以便每次使用类构造函数时,其变量都会添加到行中Solar System.csv(即所需的输出)
  2. 我不介意这是否是用另一个模块完成的,我研究了 pandas 但认为这会更难,但我愿意接受任何使用这个的建议。
  3. 如果在使用构造函数时无法做到这一点,而是必须在类之外完成,或者稍后我该如何实现。

谢谢,顺便说一句,我真的在语法上很挣扎,所以你能不能更深入地解释任何答案,这真的有助于我的理解。

EDIT1:我不确定还有哪些其他代码可以帮助人们回答这个问题,所以我将发布我所有的代码并使用一些注释来表示感兴趣的领域。

    import math, random, pygame, time, sys, csv
from pygame.locals import *
pygame.init()
canvasw = 1366
canvash = 768
window = pygame.display.set_mode((canvasw, canvash), pygame.FULLSCREEN)
planetquantity = 0
planetcolour = (150, 150, 150)
showtracers = False

def export():
    global csv_file
    with open('Solar System.csv', mode='w') as csv_file:
        writer = csv.DictWriter(csv_file, fieldnames = ["Name", "Constant", "Height", "Period", "Tier", "Parent", "Size"])
        writer.writeheader()
        
class planet():
    def __init__(self, constant, parent, angle, tier):
        global csv_file ## this is the main area where the problem is, the rest of the code works as intended.
        self.childlist = []
        self.constant = constant
        self.parent = parent
        self.angle = angle
        self.pos = (0, 0)
        self.tier = tier
        self.height = random.randint(50, 100) * self.parent.constant / self.tier
        self.period = math.sqrt((self.height ** 3) * self.parent.constant)
        self.size = int((self.constant / (self.tier / 1.0)) * 10)
        self.writer = csv.DictWriter(csv_file, fieldnames = ["Name", "Constant", "Height", "Period", "Tier", "Parent", "Size"])
        self.writer.writerow({"Name": "Bob", "Constant": str(self.constant), "Height": str(self.height), "Period": str(self.period), "Tier": str(self.tier), "Parent": "Jeff", "Size": str(self.size)})
        
    def __str__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

    def generatemoons(self, maxtier):
        global planetquantity
        if self.tier != maxtier:
            for i in range(0, random.randint(0, 5)):
                tempconstant = self.constant  / random.uniform(1.0, 3.0)
                tempangle= random.randint(0, 360)
                temptier = self.tier + 1
                self.childlist.append(planet(tempconstant, self, tempangle, temptier))
                planetquantity += 1
                self.childlist[i].generatemoons(maxtier)

    def draw(self):
        if len(self.childlist) > 0:
            for i in range(0, len(self.childlist)):
                pygame.draw.circle(window, planetcolour, self.childlist[i].pos, self.childlist[i].size)
                if showtracers == True:
                    pygame.draw.line(window, planetcolour, self.pos, self.childlist[i].pos, 1)
                self.childlist[i].draw()

    def updatemoons(self):
        if len(self.childlist) > 0:
            for i in range(0, len(self.childlist)):            
                self.childlist[i].angle += (365 / self.childlist[i].period)
                x, y = self.pos
                height = self.childlist[i].height
                newx = int(x + math.sin(math.radians(self.childlist[i].angle)) * height)
                newy = int(y + math.cos(math.radians(self.childlist[i].angle)) * height)
                self.childlist[i].pos = (newx, newy)
                self.childlist[i].updatemoons()
class sun():
    def __init__(self, constant, tier):
        self.constant = constant
        self.tier = tier
        self.childlist = []
        self.pos = (int(canvasw / 2), int(canvash / 2))
        self.size = 40

    def __str__(self):
        return str(self.__class__) + ": " + str(self.__dict__)

    def generatemoons(self):
        global planetquantity
        if self.tier > 0:
            for i in range(0, random.randint(0, 5)):
                tempconstant = self.constant  / random.uniform(1.0, 3.0)
                tempangle= random.randint(0, 360)
                temptier = 1
                self.childlist.append(planet(tempconstant, self, tempangle, temptier))
                planetquantity += 1
                self.childlist[i].generatemoons(self.tier)

    def draw(self):
        pygame.draw.circle(window, planetcolour, self.pos, self.size)
        for i in range(0, len(self.childlist)):
            pygame.draw.circle(window, planetcolour, self.childlist[i].pos, self.childlist[i].size)
            if showtracers == True:
                pygame.draw.line(window, planetcolour, self.pos, self.childlist[i].pos, 1)
            self.childlist[i].draw()    

    def updatemoons(self):
        if len(self.childlist) > 0:
            for i in range(0, len(self.childlist)):            
                self.childlist[i].angle += (365 / self.childlist[i].period)
                x, y = self.pos
                height = self.childlist[i].height
                newx = int(x + math.sin(math.radians(self.childlist[i].angle)) * height)
                newy = int(y + math.cos(math.radians(self.childlist[i].angle)) * height)
                self.childlist[i].pos = (newx, newy)
                self.childlist[i].updatemoons()
export() ## Here I called export before anything else thinging that if I opened my file as the first thing it would stay open for when class planets start getting added.
sun = sun(5.5, 1)
sun.generatemoons()
for i in range(0, len(sun.childlist)):
    print(sun.childlist[i])
print(planetquantity)
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
##    start = time.time()
    sun.updatemoons()
    sun.draw()
    pygame.display.flip()
    window.fill((0, 0 , 0))
##    end = time.time()
##    print(end - start)

标签: pythonpython-3.x

解决方案


推荐阅读