Basically i have a code which inputs 2 random numbers for strength and skill. These 2 inputs i would like to be saved on a notepad. The number generates a random number for strength and skill and i would like the number to saved on the notepad every time. So when i look back on the notepad it shows the last number which were generated. This is my code so far:
import random
playname1 = str(input("Enter player one name"))
print("Welcome",playname1)
strength1 = random.randint(1,12)
strength2 = random.randint(1,4)
strength3 = (strength1/strength2)
strength4 = round(strength3)
strength5= (10+strength4)
print ("Your strength is...",strength5)
skill1 = random.randint(1,12)
skill2 = random.randint(1,4)
skill3 = (skill1/skill2)
skill4 = round(skill3)
skill5= (10+skill4)
print ("Your skill is...",skill5)
The next part of the code i would like to be the two numbers for strength and skill to be save on a notepad.
the easiest way is
import os
strength5,skill5 =10,20
with open("data.txt") as f:
f.write("%s %s"%(strength5, skill5))
os.startfile("data.txt")
assuming I understand what you mean by "save on notepad" (eg. you dont mean write it down on a sticky note?)
You didn't specify the version of Python you are using, but according to your syntax, I assume you are using Python3? First of all, you don't need to do str(input(...)) - that's already a str.
In Python3, the correct way to write to a file is:
with open('text.txt', 'w') as f:
print('a sentence', file=f) // this will add a new line at the end automatically
// or you can do:
// f.write('a sentence\n')
// since write doesn't add new line automatically, you need to explicitly type \n
Open the file in your initialization.
f = open('output.txt', 'w')
Note that this opens it in write mode so all previous data are erased. If you want to append use
f = opr('output.txt', 'a')
Now just write the text data
datatxt = ' '.join(str(strength5), str(skill5))
f.write(datatxt)
After you completely finish
f.close()
Related
I am trying to convert from string to float. I am pulling the text from a file. Any help or hints would be greatly accepted. I am a newbie on coding. Thanks in advance.
def main():
name =["","","","","",""]
lname = ["","","","","",""]
grade = [0,0,0,0,0]
#total = 0
#count = len(name)
#average = total / count
# for i in range(len(grade)):
# total += grade[i]
#Intro
print("Grades Processing App!\n")
infile = open("gradestest.txt", "r")
for n in range(5):
line = infile.readline()
#split data into 3 fields
name[n], lname[n], grade[n] = line.split(",")
grade[n] = float(grade[n])
#infile.close()
#Display data on screen
print("Name\t\t\tGrade")
print("--------------------")
for i in range(5):
print(name[i], "\t", lname[i], "\t", grade[i])
print('\n')
infile.close()
#for n in range(len(grade)):
#total += grade[n]
# count +1
# print(average)
print('Enter the following student information')
FirstName = input("\tFirst name: ")
LastName = input("\tLast name: ")
Grade = float(input("\tTest grade : "))
infile = open("gradestest.txt", "a")
infile.write(name + "," + lname + "," + float(grade) + "\n")
infile.close()
main()
The problem in your code you can't write float values to file. You can only write string value, you can convert it to float when reading the file.
def main():
print("Grades Processing App!\n")
with open('test.txt') as fp:
data = [line.strip().split(",") for line in fp]
#Display data on screen
print("Name\t\t\tGrade")
print("--------------------")
for name, lname, grade in data:
print(name, "\t", lname, "\t", grade)
grades_avg = sum([float(val[2]) for val in data])/len(data)
print("\nAverage:", grades_avg)
print('\nEnter the following student information')
fname = input("\tFirst name: ")
lname = input("\tLast name: ")
grade = input("\tTest grade : ")
with open("test.txt", "a") as fp:
fp.write(fname + "," + lname + "," + grade + "\n")
main()
Hmmm...so there is quite a bit to discuss I think.
1) First, we note that in python you don't need to allocate memory for your objects. Hence, declaring the size and content of your variables is unnecessary. Python is dynamic, hence one would simply say, "x=[]", to begin a list. and then "x.append(7)" to append a 7 to a list. If you are using ipython (highly recommended) then you can play around with variables on-the-fly and see what they do. For example x.(press tab) will show you all the "methods" available for lists.
2) There are many functions in python that simplify doing repeated tasks. For example, the join method for strings, inserts any string between the sequence of strings your provide. Another example is that open() automatically closes files if the variable isn't used anymore, hence in python you can normally open, read, and close a file in one line.
3) Python highly revolves around iterators that allow you to simplify many many tasks. These include builtins, like sorted, reversed, map, filter, range, etc. It is highly recommended to become familiar with those, as they will greatly enhance your code.
Lets simplify your code a bit:
# Read all lines at once. No need to say 'r', that is the default.
# The file closes automatically when the variable falls out of scope.
lines = open('gradestest.txt').readlines()
# Split each line. You can do it all at once in a list comprehension.
lines = [line.split(',') for line in lines]
# Leaves all the entries alone but the last one. Python can access backwards.
# The line[:-1] means to access everything but the last item as a list.
# The line[-1] means to access the last item (which is grade).
lines = [line[:-1]+[float(line[-1])] for line in lines]
# There are other ways to read your file as well (probably faster).
# Python has a huge library of modules, like the csv module which is for
# opening and reading csv files.
# The join method inserts strings between other strings. The map function
# takes each item in an object and applies the given function to them. Hence,
# map(str,line) turned all the items into a string (including the item you
# made a float earlier.
print("Grades Processing App!\n")
print("Name\t\t\tGrade")
print("--------------------")
print('\n'.join('\t'.join(map(str,line)) for line in lines))
# Not quite sure what this code was for. You don't use your variables
# anywhere. Also you run float(grade) which I think will error, since
# grade is a list. Anyway, I think you meant to append to the file
# some new inputs.
print('Enter the following student information')
FirstName = input("\tFirst name: ")
LastName = input("\tLast name: ")
Grade = float(input("\tTest grade: "))
open('gradestest.txt','a').write(','.join([FirstName,LastName,Grade])+'\n')
Don't think I answered the original question. If you want to find an average in python, there are two builtin commands len() and sum() which count the number of items in a list and add up the items in a list. For example,
grades = [1,2,3,4,5]
average = sum(grades)/len(grades)
I know this is a lot more than you asked for, but since I left some long tips in the comments, I pasted them here with examples.
A tip about files: you can use with open('myfile.txt', 'r') as infile: and put the code that uses the file in that block under it. Once the execution of code leaves that block, the file is reliably closed - even in the case of an exception being thrown.
To address the question in your post, converting text to a float or int value is pretty simple. The only trouble is when the string data isn't in a format that can be converted to an int or float. The exception handling below will make your program a bit more robust and it won't blow up when the conversion fails. But looking at what you had in your code should work.
with open('gradestest.txt', 'r') as infile:
for line_no, line in enumerate(infile):
try:
name, lname, grade = line.split(',')
grade = float(grade)
except ValueError as ve:
print(f"Warning, file format incorrect on line "
f"{line_no + 1}: {ve}")
I added some fault tolerance to the loop that reads in grades. When .split() doesn't produce the right number of items, or float() fails trying to convert a non-numeric string, a ValueError is raised. The except block catches the ValueError and prints a warning about the file format, but the loop can continue to try and process the rest of the file.
Rather than have lists of data that rely on the index to associate different data with the same student, create a Student class that has data members for name and grade. That way you can iterate over the student list rather than iterating over a range of indices.
class Student:
def __init__(self, name, lname, grade=None):
self.name = name
self.lname = lname
self.grade = grade
The above isn't what some may consider a proper implementation of a class because we'll be accessing the data members directly from other code in your program. Since this is a very simple program that's just processing file data, and we only have three pieces of data to manage, we'll flex the coding standards a bit.
Now you have a way to reference grade and student data by attribute name on the student objects. And to be able to grab the list of students at different points in the program, we'll add them to a list.
student_list = []
with open('gradestest.txt', 'r') as infile:
for line_no, line in enumerate(infile):
try:
name, lname, grade = line.split(',')
grade = float(grade)
student_list.append( Student(name, lname, grade) )
except ValueError as ve:
print(f"Warning, file format incorrect on line "
f"{line_no + 1}: {ve}")
Then later in the program when we want to list out the students and their grades:
print(f"{'name':<20} Grade") # Pads 'name' to 20 characters with spaces.
for st in student_list:
print(f"{st.name+' '+st.lname:<20} {st.grade}")
I'm using f-strings to format the text. The text between curly braces is interpreted as Python code and returns strings at the positions in the string where they're at. The :<20 left-aligns and pads the text with spaces.
One last suggestion. This might be a little advanced, suppose you're maintaining student records and want to be able to save the information to a file, then come back to your program later and load your student objects back up with all their information in them, you could use the pickle module for that (although you might also consider a simple database - the sqlite module is pretty good)
Pandas is also a good option if you're working with tabulated student data - it can save its dataframes to file and retrieve them pretty easily.
Anyway, here's pickle:
import pickle
...
# Somewhere in your code...
save_file_y_n = input("Do you want to save student data? ")
if save_file_y_n.lower() in ['y', 'yes']:
file_name = input("Name of file: ")
# Write the Students out to a file.
pickle.dump(student_list, open(file_name, 'wb+'))
...
# Somewhere else in your code - or another script/program..
if load_file_y_n.lower() in ['y', 'yes']:
file_name = input("File name for student records: ")
# Reconstructs the Student objects from the file data
# with their name, lname, grades and any other attributes
# you may have added:
student_list = pickle.load(open(file_name, 'rb'))
print("List of students:")
for st in student_list:
print(f"st.name")
It's always a great idea to back your data up regularly in case the student data file gets somehow corrupted or accidentally deleted. You could even implement some code in your program to save student data in a new file each day and load the latest when the program starts.
A little information on this in case you're curious and not overwhelmed already https://wiki.python.org/moin/UsingPickle
Another option for saving application information is the json module. It can write basic data objects out to a file using plain text. https://docs.python.org/3/library/json.html
And of course you could use CSV (comma separated values) - there's a csv module for that, https://docs.python.org/3/library/csv.html?highlight=csv#module-csv.
Okay, So I´m doing a program that simulates dice rolls and then saves them to a file.
I thought that the easiest option, in my opinion, would be to just save every single iteration of the loop and save the print to the file line by line. But unfortunately, I cannot figure it out.
import random
output=[]
order=0
inpu_t=int(input("Enter the number of simulated throws: "))
f = open('file.txt','w')
figures = (0,)*6
for i in range(inpu_t):
order = order+1
throw = random.randint(1, 6)
figure = figures[throw -1]+1
print(order,'.throw and {}-times fell the number {}.'.format(figure, throw ))
output.append(order)
output.append(figure)
output.append(throw )
figures = figures[:throw -1]+(figure,)+figures[throw :]
print("\n")
with open('file.txt', 'w') as f:
for item in output:
f.write("%s" % item)
for i in range(6):
print('The number {} fell {}-times.'.format(i+1, figures[i]))
Secondly, I thought I could save all the variables to the list and then somehow through some function save it to a file.
output.append(order)
output.append(figure)
output.append(throw )
There I added all the data to the list.
with open('file.txt', 'w') as f:
for item in output:
f.write("%s" % item)
I added it to the file here.
My output in the file is this: "115216314412511"
I don't know how I should do it so that all 3 numbers are would be together in one line like in the code.
print(order,'.throw and {}-times fell the number {}.'.format(figure, throw ))
Append a Carriage Return "/r" with in the for loop after the append throw
hi the better way is to use logging instead to open each time file
read here : How to write to a file, using the logging Python module?
I am currently keeping high scores into a text file called "score.txt". The prgoram works fine, updating the file with the new high scores as normal. Except that every time the program updates the file, there is always one blank line before the first high score, creating an error when I try to save the scores the next time. The code:
scores_list = []
score = 10
def take_score():
# Save old scores into list
f = open("score.txt", "r")
lines = f.readlines()
for line in lines:
scores_list.append(line)
print scores_list
f.close()
take_score()
def save_score():
# Clear file
f = open("score.txt", "w")
print >> f, ""
f.close()
# Rewrite scores into text files
w = open("score.txt", "a")
for i in range(0, len(scores_list)):
new_string = scores_list[i].replace("\n", "")
scores_list[i] = int(new_string)
if score > scores_list[i]:
scores_list[i] = score
for p in range(0, len(scores_list)):
print >> w, str(scores_list[p])
print repr(str(scores_list[p]))
save_score()
The problem mentioned happens in the save_score() function. I have tried this related question: Removing spaces and empty lines from a file Using Python, but it requires I open the file in "r" mode. Is there a way to accomplish the same thing except when the file is opened in "a" mode (append)?
You are specifically printing an empty line as soon as you create the file.
print >> f, ""
You then append to it, keeping the empty line.
If you just want to clear the contents every time you run this, get rid of this:
# Clear file
f = open("score.txt", "w")
print >> f, ""
f.close()
And modify the opening to this:
w = open("score.txt", "w")
The 'w' mode truncates already, as you were already using. There's no need to truncate, write an empty line, close, then append lines. Just truncate and write what you want to write.
That said, you should use the with construct and file methods for working with files:
with open("score.txt", "w") as output: # here's the with construct
for i in xrange(len(scores_list)):
# int() can handle leading/trailing whitespace
scores_list[i] = int(scores_list[i])
if score > scores_list[i]:
scores_list[i] = score
for p in xrange(len(scores_list)):
output.write(str(scores_list[p]) + '\n') # writing to the file
print repr(str(scores_list[p]))
You will then not need to explicitly close() the file handle, as with takes care of that automatically and more reliably. Also note that you can simply send a single argument to range and it will iterate from 0, inclusive, until that argument, exclusive, so I've removed the redundant starting argument, 0. I've also changed range to the more efficient xrange, as range would only be reasonably useful here if you wanted compatibility with Python 3, and you're using Python 2-style print statements anyway, so there isn't much point.
print appends a newline to what you print. In the line
print >> f, ""
You're writing a newline to the file. This newline still exists when you reopen in append mode.
As #Zizouz212 mentions, you don't need to do all this. Just open in write mode, which'll truncate the file, then write what you need.
Your opening a file, clearing it, but then you open the same file again unnecessarily. When you open the file, you print a newline, even if you don't think so. Here is the offending line:
print >> f, ""
In Python 2, it really does this.
print "" + "\n"
This is because Python adds a newline at the end of the string to each print statement. To stop this, you could add a comma to the end of the statement:
print "",
Or just write directly:
f.write("my data")
However, if you're trying to save a Python data type, and it does not have to be human-readable, you may have luck using pickle. It's really simple to use:
def save_score():
with open('scores.txt', 'w') as f:
pickle.dump(score_data, f):
It is not really answer for question.
It is my version of your code (not tested). And don't avoid rewriting everything ;)
# --- functions ---
def take_score():
'''read values and convert to int'''
scores = []
with open("score.txt", "r") as f
for line in f:
value = int(line.strip())
scores.append(value)
return scores
def save_score(scores):
'''save values'''
with open("score.txt", "w") as f
for value in scores:
write(value)
write("\n")
def check_scores(scores, min_value):
results = []
for value in scores:
if value < min_value:
value = min_value
results.append(value)
return resulst
# --- main ---
score = 10
scores_list = take_score()
scores_list = check_scores(scores_list, score)
save_score(scores_list)
I am banging my head agaisnt a wall trying to figure out something that is simple.
Basically I have a .CSV with names in and test scores e.g.
Brad 4, 5, 7, 7
Dan 3, 6, 2, 7
What I want to do is write code that first all of prints out the tests scores. This bit works fine.
The aspect that I can not get to work is the part were the program reads the names, in the CSV. If the name is present it will append the CSV with the new score at the start. So insert the new value at array position 1.
If the name is not present in the CSV it will add name and then again insert the value at array position 1.
Here is the code that does not work currently, I don't believe it to be complicated however I must be thinking about it wrong.
import csv
def names():
global fn
fn = input("please enter first name \n").title()
namecheck = False
while namecheck == False:
nc = input("you have entered " + fn + " are you sure \n 1) Yes \n 2) No")
if nc == "1":
quiz()
namecheck = True
if nc =="2":
names()
def quiz():
option = input("do you want to print or append? \n 1) Print 2) Append")
if option =="1":
f = open('namelist.csv', 'r')
a = f.read()
print(a)
if option =="2":
score = input("please enter score")
score = int(score)
with open('namelist.csv', 'rt') as f:
reader = csv.reader(f, delimiter=',')
for row in reader:
for field in row:
if field == fn:
XXXXXXXX <--- this is were I think I am going wrong.
names()
when you declare a def, you have to indent the entire section.
def quiz():
[-->INDENT HERE!] option = input("do you want to print or append? \n 1) Print 2) Append")
[-->INDENT HERE!] rest of def..
#back to main statements..
(Of course I don't mean for you to type "[-->INDENT HERE!]" literally)
Do you have to literally write to the file every time someone adds a new score or a new name? If writing to file at the end of program is an option, I'd suggest collecting all info ahead of time and then writing the data in bulk toward the end..that way you could maintain everything in memory and do the I/O with file in one go, sparing you a lot of file operations and giving you the convenience of working with python data structures such as dicts/sets etc....
If that's not an option...
Looking up names by reading the file is really inefficient as you are reading the entire file just to see if the name is present.
I'd recommend using a dict to store the list of names you've already entered. This way checking the dict to see if the name is present or not is much more efficient...You could try storing the dict with key=name and value=line number on which you entered the name while you wrote to csv.
That way if you found the name in dict, you can go to the particular line and then append your data like this:
Start reading and writing on specific line on CSV with Python
To insert an element in the first position (i am assuming this is after the name), you could do something like:
l = line.split(",")
#assumes first element is the name of the person
l.insert(1, new_score) # 1 is the position you want to insert the data
#then insert this data into a_NEW_CSV file, as writing to same CSV at same line is difficult...
See this for more details: Replace data in csv file using python
I've been going through the exercises in this book and I've hit a bit of a road block. The challenge is to:
"Improve the Trivia Challenge game so that it maintains a high-scores list in a file. The program should record the player's name and score. Store the high scores using a pickled object."
I've managed to save scores to a list and then append this list to a dat file. However, when I try to view the scores/read the file it only seems to show the first score entered. I took a look at the bat file and it seems to be dumping the list correctly, so I'm wondering if I'm messing up the retrieval part?
Thanks for reading
Here's the code (BEFORE):
def high_score():
"""Records a player's score"""
high_scores = []
#add a score
name = input("What is your name? ")
player_score = int(input("What is your score? "))
entry = (name, player_score)
high_scores.append(entry)
high_scores.sort(reverse=True)
high_scores = high_scores[:5] # keep only top five
# Open a new file to store the pickled list
f = open("pickles1.dat", "ab")
pickle.dump(high_scores, f)
f.close()
choice = None
while choice !="0":
print(
"""
0 - Quit
1 - Show high scores
"""
)
choice = input("choice: ")
print()
# exit
if choice == "0":
print("Goodbye")
# show a score
if choice == "1":
f = open("pickles1.dat", "rb")
show_scores = pickle.load(f)
print(show_scores)
f.close()
input("\n\nPress enter to exit.")
Solution(AFTER):
def high_score():
"""Records a player's score"""
# no previous high score file
try:
with open("pickles1.dat", "rb") as f:
high_scores = pickle.load(f)
except EOFError:
high_scores = []
#add a score // Do current stuff for adding a new score...
name = input("What is your name? ")
player_score = int(input("What is your score? "))
entry = (name, player_score)
high_scores.append(entry)
high_scores.sort(reverse=True)
high_scores = high_scores[:5] # keep only top five
# dump scores
with open("pickles1.dat", "wb") as f:
pickle.dump(high_scores, f)
f = open("pickles1.dat", "ab")
# ^
You have opened the file in "append" mode. That's fine, but it's probably not doing what you want. each time you try to save data to such a file, it is tacked on the end. You'd have to read every single item you ever wrote to get to the most recently written. instead, open the file in write mode. This way, its contents will be replaced every time:
f = open("pickles1.dat", "wb")
alternatively, you can use appending, but you'll have to call pickle.load() repeatedly to see all of the written values. Here's pseudocode, first for the former, with "w"
scores = pickle.load(open('scores.dat', 'rb'))
scores.append(123)
pickle.dump(scores, open('scores.dat', 'wb'))
and the latter:
pickle.dump(123, open('scores.dat', 'ab'))
scores = []
with open('scores.dat', 'rb') as f:
while True:
try:
scores.append(pickle.load(f))
except EOFError:
break
I hope you can see why I think the former (overwriting) is nicer; it's much simpler.
There are a few problems with your code. #TokenMacGuy has identified one, which is that you're appending your results onto the end of the output file, rather than overwriting the previous values.
There is a more fundamental issue though. When you run the highscores function, you are always starting with an empty high score list. You then add a single score to it, and write it out. With this structure, you will never have more than one score being written at a time (and so even if you get it to read back what you've written properly, it will only get a 1-element list).
What you need to do is add some code to load the high score list from your file at the start of the function, before you add the new value. You need to put in a special case for when there is no previous high score file, but that's not too dificult with a try/except block. Here's some abbreviated code:
def high_score():
try:
with open("pickles1.dat", "rb") as f:
high_scores = pickle.load(f)
except FileNotFoundError:
high_scores = []
# do current stuff for adding a new score, sorting and slicing
with open("pickles1.dat", "wb") as f: # "wb" mode overwrites the previous file
pickle.dump(high_scores, f)
# do other stuff, like displaying high_scores
A benefit to this approach is that you don't need to reread the file later if the user asks for it, since the high_scores list will be up to date already.