This question already has answers here:
File Sorting in Python
(3 answers)
Closed 6 years ago.
I have a highscore file for a minesweeper game I am creating and each time after it appends with the new scores, I want it to sort per break line.
I am using:
def save_score(score):
name = input("type a name")
file = open("highscores.txt", "a")
file.write("Table: "+str(GRID_TILES)+"x"+str(GRID_TILES)+"\t mode:"+str(Dif)+"\t score:"+str(score)+"\t name:"+str(name)+"\n")
file.close()
Which comes out in this format:
table: 10x10 mode: easy score: 7592 name:Test
table: 5x5 mode: medium score: 2707 name:Test
How can I make it so that after either the file.write or the file.close it sorts the file per line?
I want it to be sorted by table only. It doesn't matter in what order, as long as all the tables that are 7x7 go by those that are also 7x7.
I have tried doing this:
def save_score(score):
name = input("type a name")
file = open("highscores.txt", "a")
file.write("table: "+str(GRID_TILES)+"x"+str(GRID_TILES)+"\t mode: "+str(Dif) +"\t score: "+str(score)+"\t name: "+str(name)+"\n")
file.close()
file = open("scores.txt", "r")
file2 = open("highscores.txt", "w")
file2.writelines(sorted(file, key=lambda line:str(line.split()[0])))
file.close()
file2.close()
I want to keep my code as short as possible, as the entire minesweeper will take up quite some ammount of code.
def save_score(score):
name = input("type a name")
with open("scores.txt", "a") as file:
file.write("table: {}x{}\t mode: {}\t score: {}\t name: {}\n".format(
GRID_TILES, GRID_TILES, Dif, score, name))
with open("scores.txt") as file, open("highscores.txt", "w") as file2:
file2.writelines(sorted(file, key=lambda line: line.split()[1]))
Thanks to Frerich Raabe for supplying me with an answer!
Here is one way:
import shutil
from tempfile import NamedTemporaryFile
def insert_sorted(file_obj, in_line):
flag = False
with NamedTemporaryFile(delete=False, mode="w+") as temp:
try:
val = int(in_line.split()[-2])
except (IndexError, ValueError):
raise Exception("Invalid format")
for line in file_obj:
try:
lineval = int(line.split()[-2])
except (IndexError, ValueError):
print("""following line has an invalid format,\
and gets escaped\n{}""".format(line))
else:
# Write larger score first when we find smaller score
if lineval <= val:
temp.write(in_line)
temp.write(line)
flag = True
break
else:
temp.write(line)
for line in file_obj:
temp.write(line)
# if the score of the in_line is grater than all the lines write it at the trailing.
if not flag:
temp.write(in_line)
return temp
with open(file_name) as f:
in_line = "table: 10x10 mode: easy score: 8592 name:Test"
temp = insert_sorted(f, in_line)
shutil.move(temp.name, file_name)
Related
So I've written a simple program that allows user to enter a line they would like to edit and text they would like to put into that line
def edit_line(file):
a_file = open(file, 'r')
list_of_lines = a_file.readlines()
list_of_lines[int(input('What line would you like to edit?: ')) - 1] = input('Write your text here: ') + '\n'
a_file = open(file, 'w')
a_file.writelines(list_of_lines)
a_file.close()
edit_line('sample.txt')
When I run the program it works fine. However, It asks the user to input the text first and the line number second.
What is the reason for this and how can I fix it?
If you want to fix the problem, just split the one line into two:
Instead of:
list_of_lines[int(input('What line would you like to edit?: ')) - 1] = input('Write your text here: ') + '\n'
Do:
index = int(input('What line would you like to edit?: ')) - 1
list_of_lines[index] = input('Write your text here: ') + '\n'
And as the answer #Guy linked explains, when you are doing an assignment line of code, the right hand (value of the variable) is run before the left side.
Validation is everything! What would happen if the user's input for the line number wasn't within the range of lines read from the file?
Here's a more robust approach:
def edit_line(filename):
with open(filename, 'r+') as file:
lines = file.readlines()
while True:
try:
lineno = int(input('What line would you like to edit: '))
if 0 <= lineno < len(lines):
lines[lineno] = input('Write your text here: ') + '\n'
file.seek(0)
file.writelines(lines)
file.truncate()
break
else:
raise ValueError('Line number out of range')
except ValueError as e:
print(e)
edit_line('edit.txt')
I have a code that i am writing to read a txt file and report sum, average, ect... but I also need it to recognize when the txt file is empty or has no numbers in it, and not crash. i have tried os.stat(f).st_size == 0, and os.path.getsize(f) == 0:, and reading the first character too. for some reason my code is not picking up on the exception and keeps continuing on with the rest of the code and then crashes when trying to divide by zero to find the average. I am also not using any external libraries.
#the below code asks for the file name and opens the file :)
while (True):
try:
filename = input("What file would you like to acess?: ")
f = open(filename, "r")
except IOError:
print("File", filename, "could not be opened")
except:
if os.path.getsize(f) == 0:
print("There are no numbers in", filename)
else:
break
#the below line displays the file name :)
print("File Name: ", f.name)
#the below code calculates the sum and prints it :)
sum=0
for n in f:
n=n.strip()
sum=sum+int(n)
print("Sum: ", sum)
#the below code calculates the number of lines and prints it :)
with open(filename, "r") as f:
count = 0
for line in f:
if line != "\n":
count += 1
print("Count: ", count)
#the below code calculates the average and prints it :)
avg = sum/count
print("Average: ", avg)
I'm working on a Python course on Coursera. One of the assignments is to read input from a text file, extract the email addresses on lines starting with "From:", and then print both email addresses and the number of lines that start with "From:". I got it to work after a little effort, but I wanted to see if my code can be cleaned up.
If I shouldn't worry so much about writing elegant code if I'm just in my second week of Python, you can go ahead and let me know.
fname = input("Enter file name: ")
if len(fname) < 1:
fname = "mbox-short.txt"
fh = open(fname)
text = fh.read()
lines = text.splitlines()
count = 0
from_lines = list()
for line in lines:
if 'From:' in line:
count += 1
from_lines.append(line)
email = list()
for line in from_lines:
email = line.split()
print(email[1])
print("There were", count, "lines in the file with From as the first word")
You can get the work done with only one loop like this:
fname = input("Enter file name: ")
if len(fname) < 1:
fname = "mbox-short.txt"
fh = open(fname)
lines = text.readlines() #readlines creates a list of lines from the file
count = 0
for line in lines:
if 'From:' in line:
count += 1
email = line.split()[1]
print(email)
fh.close() # always close the file after use
print("There were {} lines in the file with From as the first word".format(count))
You never close the file. Anyway you shouldn't be handling the files manually, and instead use a context manager:
with open(fname) as as fh:
...
If you are going to iterate the file line-by-line, there is no need to save to memory the whole content of the file to a string. Files are iterators themselves and iterating over them gives the lines:
for line in fh:
There is no need for two loops - if you just found there is an email in a line, why save it for later? Just use it right there!
You might check if the line startswith instead of using in.
All together might give:
fname = input("Enter file name: ")
if len(fname) < 1:
fname = "mbox-short.txt"
count = 0
with open(fname) as fh:
for line in fh:
if line.startswith('From:'):
count += 1
email = line.split()[1]
print(email)
print("There were", count, "lines in the file with From as the first word")
Here:
fname = input("Enter file name: ")
if not(fname): fname = "mbox-short.txt"
with open(fname) as fh:
lines = fh.readlines()
count = 0
from_lines = [line for line in lines if line.startswith('From:')]
for line in from_lines:
count += 1
email = line.split()
print(email[1])
print("There were",count,"lines in the file with From as the first word")
Or...
fname = input("Enter file name: ")
if not(fname): fname = "mbox-short.txt"
with open(fname) as fh:
lines = fh.readlines()
from_lines = [line for line in lines if line.startswith('From:')]
for line in from_lines: print(line.split()[1])
print(f"There were {len(from_lines)} lines in the file with From as the first word")
Am writing a program that opens a file and looks for line which are like this:
X-DSPAM-Confidence: 0.8475.
I want to use the split and find function to extract these lines and put it in a variable. This is the code I have written:
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
fh = open(fname,'r')
total = 0
for line in fh:
if not line.startswith("X-DSPAM-Confidence:"): continue
Please, Please I am now beginning in python so please give me something simple which I can understand to help me later on. Please, Please.
I think the only wrong part is not in if :
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
fh = open(fname,'r')
total = 0
lines = []
for line in fh:
if line.startswith("X-DSPAM-Confidence:"):
lines.append(line)
First receive the input with raw_input()
fname = raw_input("Enter file name: ")
Then check if the input string is empty:
if not fname:
fname = 'mbox-short.txt'
Then, open the file and read it line by line:
lines = []
with open(fname, 'r') as f:
for line in f.readlines():
if line.startswith("X-DSPAM-Confidence:"):
lines.append(line)
The with open() as file statement just ensures that the file object gets closed when you don't need it anymore. (file.close() is called automatically upon exiting out of the with clause)
I know where this one is coming from as I've done it myself some time ago. As far as I remember you need to calculate the average :)
fname = raw_input("Enter file name: ")
fh = open(fname)
count = 0
sum = 0
for line in fh:
if not line.startswith("X-DSPAM-Confidence:") : continue
count = count + 1
pos = line.find(' ')
sum = sum + float(line[pos:])
average = sum/count
You're very close, you just need to add a statement below the continue adding the line to a list.
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
fh = open(fname,'r')
total = 0
lines = []
for line in fh:
if not line.startswith("X-DSPAM-Confidence:"):
continue
lines.append(line) # will only execute if the continue is not executed
fh.close()
You should also look at the with keyword for opening files - it's much safer and easier. You would use it like this (I also swapped the logic of your if - saves you a line and a needless continue):
fname = raw_input("Enter file name: ")
if len(fname) == 0:
fname = 'mbox-short.txt'
total = 0
good_lines = []
with open(fname,'r') as fh:
for line in fh:
if line.startswith("X-DSPAM-Confidence:"):
good_lines.append(line)
If you just want the values, you can do a list comprehension with the good_lines list like this:
values = [ l.split()[1] for l in good_lines ]
I'm currently working on a task where I must store scores in a text file. This is my code thus far:
def FileHandle():
score = str(Name) + ": " + str(correct)
File = open('Test.txt', 'a')
File.write(score)
File.close()
Name = input("Name: ")
correct = input("Number: ")
FileHandle()
My question is, how would I check already existed names in the text file and only add their score, rather than name and score, to the line it existed on?
This is what the file looks like:
Jonathon: 1
Micky: 5
How it would look after adding a score:
Jonathon: 1, 4
Mickey: 5
# The score added here is Jonathon's 4
Attempt:
# Accept scores
name = input("Name: ")
correct = input("Number: ")
if name in grade_book.keys and "," in grade_book.keys <= 2():
grade_book[name] += ',' + correct
else:
grade_book[name] = correct
If you are entering many scores at a time, I suggest reading the file into memory and working with things there. Doing an open/close on the file for every score update is very inefficient.
# Read the file into a dictionary
grade_book = {}
File = open('Test.txt', 'r')
for line in File:
name, scores = line.split(':')
grade_book[name] = scores.strip()
File.close()
print grade_book
# Accept scores
name = raw_input("Name: ")
while name != "":
correct = raw_input("Number: ")
if name in grade_book.keys():
grade_book[name] += ',' + correct
else:
grade_book[name] = correct
name = raw_input("Name: ")
# Write dictionary back to the file
File = open('Test.txt', 'w')
for name, scores in grade_book.items():
out_line = name + ':' + scores + "\n"
File.write(out_line)
File.close()
Unfortunately you would have to go over the file, find the correct line, edit it and write in a temp file and then move that file to original. Best first use a data structure like dict etc. to update scores and finally when done write or persist them.
def filehandle(name,correct):
temp = open('temp', 'wb')
with open('Test.txt', 'r') as f:
for line in f:
if line.startswith(name):
line = line.strip() + correct +'\n'
temp.write(line)
temp.close()
shutils.move('temp', 'data.txt')
You need to pass in the parameters while calling the functions.
Name = input("Name: ")
correct = input("Number: ")
filehandle(name, correct)