I want to write data to a CSV file but I can't get my code to write any variables. I am running a large number of games and I'd like to have it all in the CSV file to show the game number and the result (win/lose/draw).
def function():
#gets game result
file = open("data.csv", "w")
for i in range(10):
#function()
file.write("game i", result)
file.close()
What I'm looking to get is:
game 1, result
game 2, result
game n, result
Use a format string that will expand the variable contents:
file.write(f'game {i}, {result}')
Although I'd use the csv module since it will properly handle data columns with delimiters and/or quotes in them:
import csv
with open('data.csv', 'w', newline='') as file:
writer = csv.writer(file)
for i in range(10):
result = 'some result with , and " in it'
writer.writerow([f'game {i}', result])
Output that properly quotes a result with commas and escapes embedded quotes:
game 0,"some result with , and "" in it"
game 1,"some result with , and "" in it"
game 2,"some result with , and "" in it"
game 3,"some result with , and "" in it"
game 4,"some result with , and "" in it"
game 5,"some result with , and "" in it"
game 6,"some result with , and "" in it"
game 7,"some result with , and "" in it"
game 8,"some result with , and "" in it"
game 9,"some result with , and "" in it"
To read and parse the data:
with open('data.csv', 'r', newline='') as file:
reader = csv.reader(file)
for game, result in reader:
print(game, result)
Related
I'm creating a discord bot in python and I want to have a log system for the warn command. To set up this, I'm using a .csv file in which I write all the information I want about a user.
It's the first time I use .csv, so to manipulate the data, I take the content of the file and convert it into a list of list. One sublist = one line of the table.
After treatment, I put all the elements of each sublists side by side, separated by a ";" to store it properly in the .csv file.
The problem I have comes from this :
csvwriter = csv.writer(wfile, delimiter=";")
For each caracter in the final file, a ";" is put right after so instead of this : (abc;def;ghi), I have this : (a;b;c;d;...).
All of the code :
#commands.command()
#commands.has_any_role(765280296781742090, 765609632482721852, 882222368976670772)
async def test(self, ctx, member:discord.Member):
messages = await ctx.channel.history(limit = 1).flatten()
for each_message in messages:
await each_message.delete()
with open("ressources/logs/warn_logs.csv", 'r', newline='') as csvfile:
content = []
new_registrated = []
is_registrated = False
for line in csvfile:
line = line.split(";")
content.append(line)
for cell in content:
if cell == content[0]:
pass
else:
if int(cell[0]) == int(member.id):
is_registrated = True
cell[3] = int(cell[3])+1
cell[3] = str(cell[3])
if is_registrated == False:
new_registrated.append(str(member.id))
new_registrated.append(str(member._user))
new_registrated.append(member.nick)
new_registrated.append("1\r\n")
content.append(new_registrated)
with open("ressources/logs/warn_logs.csv", 'w', newline='') as wfile:
csvwriter = csv.writer(wfile, delimiter=";")
# for line in content:
# print(line)
# line = ";".join(line)
# print(line)
# csvwriter.writerow(line)
csvwriter.writerow("abc")
wfile.close()
csvfile.close()
What I have :
What I want :
I'm working on it for a while now so if someone could help me, I would be very greatful.
NB: I'm French, and my English isn't perfect so don't hesitate to correct me
I tried to:
Not put the delimiter : the ";" became ","
Put delimiter="smth" / =False / =None : it doesn't work
Any other character : ";" became any other character
The writerow() function expects an iterable object to write a whole row.
csvwriter.writerow("abc")
will write to the file:
a;b;c
and
csvwriter.writerow(["abc", "def"])
will write:
abc;def
If line is a list of strings then line = ";".join(line) is wrong, line should go directly to writerow(). The whole point of using a csv module in not to think about delimiters.
Also if you are using a with open(...) as f: you don't have to close the file.
I have tried to create a really simple program that counts the words that you have written. When I run my code, I do not get any errors, the problem is that it always says: "the numbers of words are 0" when it is clearly not 0. I have tried to add this and see if it actually reads anything from the file: print(data) . It doesn't print anything ): so there must be a problem with the read part.
print("copy ur text down below")
words = input("")
f = open("data.txt", "w+")
z = open("data.txt", "r+")
info = f.write(words)
data = z.read()
res = len(data.split())
print("the numbers of words are " + str(res))
f.close()
Thx in advance
This is beacuse you haven't closed the file after writing to it. Use f.close() before using z.read()
Code:
print("copy ur text down below")
words = input("")
f = open("data.txt", "w+")
z = open("data.txt", "r+")
info = f.write(words)
f.close() # closing the file here after writing
data = z.read()
res = len(data.split())
print("the numbers of words are " + str(res))
f.close()
Output:
copy ur text down below
hello world
the numbers of words are 2
After writing to f with f.write, you should close f with f.close before calling z.read. See here.
I'm a beginner at Python and I just learned about opening files, reading files, writing files, and appending files.
I would I like to implement this to a little project that I'm making that asks for the user's name and appends it to a txt file named "HallOfFame.txt"
try:
infile = open('HallOfFame.txt', 'r')
file_contents = infile.read()
print(file_contents)
infile.close()
except:
FileNotFoundError
print("No Human Has Ever Beat Me... mwah-ha-ha-ha!")
name_file = open("HallOfFame.txt", 'a')
name_record = input("Please enter your name: ")
name_file.write(str(name_record) + '\n')
name_file.close()
Everytime someone adds their name, I'd like it to become something like this:
Vix
Mike
Valerie
Something similar like that (above) where they have to run the program again to see the Hall of Fame.
Thank you!
I can understand your question. you can try using the JSON module and do something like this.
import json
list = [1, "Vix"]
with open ('HallOfFame.txt', 'w') as filehandle:
json.dump(list, filehandle)
here you can update the list every time you get input. and write it to the text file. but the appearance will look like this.
[1, "Vix"]
[2, "Mike"]
[3, "Valerie"]
count = 0
try:
infile = open('HallOfFame.txt', 'r')
file_contents = infile.readlines()
if len(file_contents) != 0:
print("\nHall of Fame")
for line in file_contents:
count += 1
print("{}. {}".format(count, line.strip()))
print()
infile.close()
except:
FileNotFoundError
print("No Human Has Ever Beat Me... mwah-ha-ha-ha!")
name_file = open("HallOfFame.txt", 'a')
name_record = input("Please enter your name: ")
name_file.write(str(name_record) + "\n")
name_file.close()
How to Overwite a line in file using python?
this is my list in text file
"Sample" , "S"
"Simple" , "T"
"test" , "S"
how to Overwite the second line?
"Simple", "T"
into
"Simple", "S"
then the text file will be change like this:
"Sample" , "S"
"Simple" , "S"
"test" , "S"
Here is my code i use function
for the flow
list = []
#put your sample csv file here
fileName = 'list.txt'
#reading file text
def openFile(filename):
content = open(filename)
lines = content.readlines()
for line in lines:
list.append(line)
return content
def mark(fileName):
flag = open(pick, "w")
choice = input("Enter number to mark: ")
for choice in list:
flag.write(choice[1].replace('"T"', '"S"')
AnyOne can help me to solve this hard problem??
I think this should be enough for your purposes.
with open(filename, 'r+') as f:
content = f.read().replace('"T"', '"S"')
f.seek(0)
f.write(content)
f.truncate()
You can try this:
list = []
#put your sample csv file here
fileName = 'list.txt'
#reading file text
def openFile(filename):
content = open(filename)
lines = content.readlines()
for line in lines:
list.append(line)
content.close()
return content
def mark(fileName):
flag = open(fileName, "w")
choice = input("Enter number to mark: ")
list[int(choice)] = list[int(choice)].replace('"T"','"S"')
for line in list:
flag.write(line)
cnt = openFile(fileName)
mark(fileName)
Input file (list.txt):
"Sample" , "S"
"Simple" , "T"
"test" , "S"
Output file (out.txt):
"Sample" , "S"
"Simple" , "S" <---- this value changed from a T to a S
"test" , "S"
I have a problem where the function just overwrites the line thats already there in a .txt file. The function is supposed to write a highscore to a file when the game quits (I have made a snake game by following a youtube tutorial). I can't quite figure out why it won't start on a new line, can anyone please explain the logic behind it, and how I fix it? I read somewhere that instead of "w" in f.open(), I should type "rb" or something. Since I'm kinda new to this "writing-to-file" thingy, I find it difficult.
Also, I want to sort the highscores from highest to lowest in the file (in other words, sort finalScore from highest to lowest). I have no idea how I should go on and code that, so I'd appreicate some help. You see, I want to print out the current highscores to the console (in order to make a scoreboad)
Heres the code:
import random
import time
name = "Andreas"
finalScore = random.randint(1,10)
def scoreToFile(finalScore):
#Has to be generated here, since we need the exact current time
currentTime = time.strftime("%c")
print("Sucsessfully logged score (finalScore) to highscores.txt")
f = open("highscores.txt", "w")
#fileOutput = [(currentTime, ":", name, "-", finalScore)]
fileOutput = [(finalScore, "-", name, currentTime)]
for t in fileOutput:
line = ' '.join(str(x) for x in t)
f.write(line + "\n")
f.close()
scoreToFile(finalScore)
Anyways, merry christmas my fellow python geeks! :D
1) one option is to open the file in append mode.
replace:
f = open("highscores.txt", "w")
with:
f = open("highscores.txt", "a")
2) another option is to replace this block,
f = open("highscores.txt", "w")
#fileOutput = [(currentTime, ":", name, "-", finalScore)]
fileOutput = [(finalScore, "-", name, currentTime)]
for t in fileOutput:
line = ' '.join(str(x) for x in t)
myfile.write(line + "\n")
f.close()
and use a with style
with open("highscores.txt", "a") as myfile:
#fileOutput = [(currentTime, ":", name, "-", finalScore)]
fileOutput = [(finalScore, "-", name, currentTime)]
for t in fileOutput:
line = ' '.join(str(x) for x in t)
myfile.write(line + "\n")
I prefer the second style as it is more safe and clean.
Mode w overwrites an existing file; mode 'a' appends to it. Also, the best way to handle a file is usually with the with statement, which ensures the closing on your behalf; so:
fileOutput = [(finalScore, "-", name, currentTime)]
with open("highscores.txt", "a") as f:
for t in fileOutput:
line = ' '.join(str(x) for x in t)
f.write(line + "\n")
For sorting, you need be able to extract the final score as a number from a line:
def minus_score(line):
return -int(line.split()[0])
then the total work will be done as:
def sorted_by_score():
with open("highscores.txt", "r") as f:
result = list(f)
return sorted(result, key=minus_score)
This will give you a list lines sorted in ascending order of score (the latter's the reason score is negating the number, though one might also choose to have it just return the number and reverse the sorting), for you to loop on and further process.
Added: so on the OP's request here's how the whole program might be (assuming the existence of a function that either plays a game and returns player name and final score, or else returns None when no more games are to be played and the program must exit).
import time
def play_game():
""" play a game and return name, finalscore;
return None to mean no more games, program finished.
THIS function you'd better code yourself!-)
"""
def scoreToFile(name, finalScore):
""" Add a name and score to the high-scores file. """
currentTime = time.strftime("%c")
fileOutput = finalScore, "-", name, currentTime
line = ' '.join(str(x) for x in fileOutput)
with open("highscores.txt", "a") as f:
f.write(line + "\n")
def minus_score(line):
""" just for sorting purposes, not called directly. """
return -int(line.split()[0])
def sorted_by_score():
""" return list of score lines sorted in descending order of score. """
with open("highscores.txt", "r") as f:
return sorted(f, key=minus_score)
def main():
while True:
game_result = play_game()
if game_result is None: break
scoreToFile(*game_result)
for line in sorted_by_score:
print(line.strip())
As others have mentioned, the problem is you're not opening the file in append mode, so it overwrites it every time rather than adding to it.
However, if you also want to keep the data in the file sorted, you do want to overwrite it each time, since the order of its contents will likely have been changed with the addition. To do that requires first reading it contents in, updating the data, and then writing it back out.
Here's a modified version of your function that does that. I also changed how the data in file is stored to what is known as Comma (or Character) Separated Values (CSV) format, because Python includes acsvmodule which makes it very easy to read, write, and do other things with such files.
import csv
import random
import time
highscores_filename = "highscores.txt"
HighScoresFirst = True # Determines sort order of data in file
def scoreToFile(name, finalScore):
currentTime = time.strftime("%c")
# Try reading scores from existing file.
try:
with open(highscores_filename, "r", newline='') as csvfile:
highscores = [row for row in csv.reader(csvfile, delimiter='-')]
except FileNotFoundError:
highscores = []
# Add this score to the end of the list.
highscores.append([str(finalScore), name, currentTime])
# Sort updated list by numeric score.
highscores.sort(key=lambda item: int(item[0]), reverse=HighScoresFirst)
# Create/rewrite highscores file from highscores list.
with open(highscores_filename, "w", newline='') as csvfile:
writer = csv.writer(csvfile, delimiter='-')
writer.writerows(highscores)
print("successfully logged score (finalScore) to highscores.txt")
# Simulate using the function several times.
name = "Name"
for i in range(1, 4):
finalScore = random.randint(1,10)
scoreToFile(name + str(i), finalScore)
time.sleep(random.randint(1,3)) # Pause so time values will vary.