Python 在类或函数中保持文件打开以便写入

Python 在类或函数中保持文件打开以便写入,python,python-3.x,Python,Python 3.x,我正在尝试编写代码,在创建类的对象时将类变量写入.csv文件。我目前的代码是: class planet(): def __init__(self, constant, parent, angle, tier): global csv_file self.writer = csv.DictWriter(csv_file, fieldnames = ["Name", "Constant", "Height", "

我正在尝试编写代码,在创建类的对象时将类变量写入.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操作。我理解这是因为我试图写入一个关闭的文件。为了解决这个问题,我尝试将
with open()
语句放在我的
\uuuu init\uuuu()
的顶部,但这不起作用,因为每当调用该类时,它都会擦除前一行,并使用自己的数据编写它

我想澄清的问题是:

  • 如何对其进行排序,以便每次使用类构造函数时,其变量都会添加到
    Solar System.csv
    中的一行(这是所需的输出)
  • 我不介意这是用另一个模块完成的,我研究了熊猫,但认为这会更难,但我愿意接受任何使用这个模块的建议
  • 如果在使用构造函数时无法做到这一点,而必须在类之外或以后才能做到这一点,我该如何实现呢
  • 谢谢,顺便说一句,我真的很难理解语法,所以你能不能解释一下任何有助于我理解的答案

    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)
    

    与我们分享“大局”。主要的课程是什么?为什么csv文件是全局的,等等。共享更多的代码。到目前为止,这个问题还不清楚。
    使用open(…)As csv_file
    关闭
    with
    块末尾打开的文件。在这种情况下,您不能将
    一起使用。相反,请在程序启动时执行
    csv\u file=open(…)
    ,并确保在程序结束时调用
    close()
    ,即使它崩溃。@BoarGules,我的程序在技术上是无限的,因为我无意打破while True循环,我可以使用
    close()
    一旦类构造函数使用完毕?如果类的方法需要文件保持打开状态,则不需要。@BoarGules,谢谢,您的解决方案成功了,顺便问一下,您知道为什么每个条目之间都有一个空的.csv行吗?