python - 在类或函数中保持文件打开以进行写入
问题描述
我正在尝试编写将类变量写入 .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__()
但这不起作用,因为每当调用该类时,它都会删除前一行并用自己的数据编写它。
为了澄清我的问题是:
- 如何对此进行排序,以便每次使用类构造函数时,其变量都会添加到行中
Solar System.csv
(即所需的输出) - 我不介意这是否是用另一个模块完成的,我研究了 pandas 但认为这会更难,但我愿意接受任何使用这个的建议。
- 如果在使用构造函数时无法做到这一点,而是必须在类之外完成,或者稍后我该如何实现。
谢谢,顺便说一句,我真的在语法上很挣扎,所以你能不能更深入地解释任何答案,这真的有助于我的理解。
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)
解决方案
推荐阅读
- android - 在警报对话框中显示 tablayout
- node.js - 按 DESC 性能排序的 Sqlite
- javascript - 使用生成的 ID 删除 Json 数据
- excel - OpenXML - 继续写入下一个工作表(百万行命中)
- laravel - SPA 使用 Laravel 5.8 / Vue - auth() 返回令牌 true 而不是令牌值
- java - 无法创建 Java 虚拟机 javaw.exe。我的世界
- java - 使用 JNI 从 Android 应用程序向 C++ 发送字符串
- java - Map-Reduce 中的洗牌
- java - Java UTF-8 URLEncoder 编码不应该的特殊字符
- javascript - 输入 autocomplete="off" 在 Chrome 最新版本中不起作用