I have a text file that contains users username, password and highest score, however I want to overwrite their high score when the achieve a high score. However I only want to overwrite that specific value and no others.
This is my text file (called 'users.txt') :
david 1234abc 34 hannah 5678defg 12 conor 4d3c2b1a 21
For example, if 'hannah' gets a new score of 15, I want to change 12 to 15
Here is what I've tried:
# splitting the file
file = open("users.txt","r")
read = file.read()
users = read.split()
file.close()
# finding indexs for username, password and score
usernamePosition1 = users.index(user)
passwordPosition1 = usernamePosition1 + 1
scorePosition1 = passwordPosition1 + 1
file = open("users.txt","a")
# setting previous high score to an integer
player1OldScore = int(users[scorePosition1])
if player1Score > player1OldScore:
# setting in back to a str for text file
player1ScoreStr = str(player1Score)
# from here on i dont really know what i was doing
users.insert([scorePosition1],player1ScoreStr)
file.write(users)
print(player2 + "\n \nAchieved a new high score")
else:
print("\n \n" + player1 + " , you didn't achieve a new high score")
Your text file format is rather brittle. If David uses "hannah" as a password, then when Hannah tries to update her score, instead of locating her score (the sixth field), it will find her name as the second field and try using the fourth field (her name) as her score! Anyone using a space in their password would also cause problems, although a sneaky person could use “abcd 1000000” as their initial password and seed their initial score as one million.
These problems can be fixed by:
Using 1 line per user, or
Searching for user names only in the first of every 3 fields
And
disallowing spaces in passwords, or
coding/encrypting the passwords
In any case, you must read in and store the existing data, and then write out the entire dataset to the file. The reason is the data is not stored in fixed-width fields. A score changing from 99 to 100 will require moving all subsequent characters of the file one character forward, which is not a modification you can make to the file without actually reading and rewriting it in it’s entirety.
You are going to need to find and replace the strings. This means you will need to format the users.txt file in a way that you are able to simply replace the user data. If you have each user and their data on a seperate line this should be fairly easy:
import string
s = open("users.txt","r+")
for line in s.readlines():
print line
string.replace(line, 'hannah 5678defg 12','hannah gfed8765 21')
print line
s.close()
You have the right idea (note that I your code will only work for 1 user, but I'll let you figure out how to extend it), but there is no way to change the file without writing the entire file.
As such I recommend something like this:
...
file = open("users.txt","w") # change this from 'a' to 'w' to overwrite
player1OldScore = int(users[scorePosition1])
if player1Score > player1OldScore:
users[scorePosition1] = str(player1Score) # change the score
file.write(" ".join(users)) # write a string with spaces between elements
print(player2 + "\n \nAchieved a new high score")
...
Related
I need to be able to read from a file and print records if a variable entered is pre-existent in the file. I have tried to open the file as 'f' however that would only read the first line in the file, heres my code:
problem = input("Please select from one of these: sink, faucet, toilet, shower, heater, other: \n")
temporaryFile = open("plumberInfo.txt" , "r")
for row in temporaryFile:
record = row.split(",")
if record[6] == problem:
Pforename = record[1]
Psurname = record[2]
Pfee = record[3]
Pexperience = record[4]
Prate = record[5]
print("You have selected", Pforename, Psurname, "they have", Pexperience , "years of experience and they specialise in", problem, "\n")
else:
print("Invalid input")
plumberSearch() #This part isn't relevant
Also below I have attached some contents of the file:
743,Auryn,Smith,42.00,6,44.50,faucet,extra
583,Michael,Lanlow,25.00,8,75.00,sink,extra
731,Hanna,Taylor,42.00,14,55.00,heater,extra
981,Tomie,Agen,32.00,6,44.50,toilet,extra
I don't understand the problem as it worked fine for when I was searching by the ID ([record0]). There is no traceback error, it just states invalid input which means record[6] != problem, however it is equal.
When I try the code on my machine, printing record shows me that the last item contains a new line character at the end. Thus when you search for sink, you're essentially doing the search sink == sink\n, hence why you get invalid input.
Reading in the file also reads in the new line, and you need to be aware. You would need to remove it before doing the comparison.
I'm making a Music Quiz for a school project.
I've made a working game however I cannot get the leaderboard (which should be text and is saved as leaderboard.txt) to show different names as it overwrites the previous name.
For example, if "Sam" was to get a score of 9 and "Ben" was to get a score of 3, it would show up as "Ben-3-9" which is not what I'm after.
I am trying to get my leaderboard to work like:
Sam - 9
Ben - 3
...
My code looks like this right now:
username = input("What is your username?")
# this will ask for the persons name
password = str(input("What is the password?"))
# this will ask for a password which has been set already
if password == "1234":
print("User Authenticated")
# if the password is incorrect, tell the user so and exit
elif password != "1234":
print("Password Denied")
exit()
# GAME
# Creating a score variable
score=0
x = 0
# Reading song names and artist from the file
read = open("songnames.txt", "r")
songs = read.readlines()
songlist = []
# Removing the 'new line' code
for i in range(len(songs)):
songlist.append(songs[i].strip('\n'))
while x == 0:
# Randomly choosing a song and artist from the list
import random
choice = random.choice(songlist)
artist, song = choice.split('-')
# Splitting the song into the first letters of each word
songs = song.split()
letters = [word[0] for word in songs]
# Loop for guessing the answer
for x in range(0, 2):
print(artist, "".join(letters))
guess = str(input("Guess the song!"))
if guess == song:
if x == 0:
score = score + 3
break
if x == 1:
score = score + 1
break
quit()
# Printing score, Then waiting to start loop again.
import time
print("Your score is", score)
print("Nice Work!")
time.sleep(3)
leaderboard = open("leaderboard.txt", "r+")
leaderboard.write(username + '-' + '{}'.format(score))
leaderboard.close()
leaderboard = open("leaderboard.txt", "r+")
leaderboardlist = leaderboard.readlines()
print(leaderboardlist)
leaderboard.close()
PS: this is not 100% my code I am trying to get help from different places as my school has not taught us how to code yet due to the pandemic closing down schools.
When you do this:
leaderboard = open("leaderboard.txt", "r+")
leaderboard.write(username + '-' + '{}'.format(score))
you open the leaderboard in read-and-write mode, but it will start writing at the beginning of the file, overwriting whatever is there. If you just want to add new scores to the leaderboard, the simplest would be to open the file in "append" mode "a":
with open("leaderboard.txt", "a") as leaderboard:
leaderboard.write(username + '-' + '{}'.format(score))
Alternatively, you could open the file in "r" mode, then first read all the lines (scores) in a list or dictionary, merge / update them with the current player's new score (e.g. adding to the last score, replacing the last score, or getting the max of the new and last score of that player), and then open the file again in "w" mode and write the updated scores. (Left as an exercise to the reader.)
The problem lies within the final few lines of code, where you are writing to the leaderboard.txt file.
Using "r+" indicates that you are updating (reading and writing) the file. Opening a file this way, moves the cursor at the beginning of the file. Therefore any attempt to write to the file will override whatever is already there.
The proper way to do it, is to open the file using "a" (or "a+" if you are planning to read as well). This is append mode and will move the cursor to the end of the file.
Some other general notes:
Use the with-as statement to handle closing the file automatically after you are done.
Use f-strings as opposed to string concatenation to increase readability
With that in mind, here's the code:
with open("leaderboards.txt", "a") as f:
f.write(f"{username}-{score}")
For more on files, check this question.
For more on f-strings, check this quite extensive overview of them.
So I have a file that looks like this
mass (GeV) spectrum (1-100 GeV)
10 0.06751019803888393
20 0.11048827045815585
30 0.1399367785958526
40 0.1628781532692572
I want to multiply the spectrum by half or any percentage, then create a new file with the same data, but the spectrum is replaced with the new spectrum multiplied by the multiplier
DM_file=input("Name of DM.in file: ") #name of file is DMmumu.in
print(DM_file)
n=float(input('Enter the percentage of annihilation: '))
N=n*100
pct=(1-n)
counter = 0
with open (DM_file,'r+') as f:
with open ('test.txt','w') as output:
lines=f.readlines()
print(type(lines))
Spectrumnew=[]
Spectrum=[]
for i in range(8,58):
single_line=lines[i].split("\t")
old_number = single_line[1]
new_number = float(single_line[1])*pct
Spectrumnew.append(new_number)
Spectrum.append(old_number)
f.replace(Spectrum,Spectrumnew)
output.write(str(new_number))
The problem I'm having is f.replace(Spectrum,Spectrumnew) is not working, and if I were to comment it out, a new file is created called test.txt with just Spectrumnew nothing else. What is wrong with f.replace, am I using the wrong string method?
replace is a function that works on strings. f is not a string. (For that matter, neither is Spectrum or Spectrumnew.)
You need to construct the line you want in the output file as a string and then write it out. You already have string output working. To construct the output line, you can just concatenate the first number from the input, a tab character, and the product of the second number and the multiplier. You can convert a number to a string with the str() function and you can concatenate strings with the + operator.
There are several more specific answers on this site already that may be helpful, such as replacing text in a file with Python.
I’m struggling to write a Python script to process a file and produce an output text file containing the tickets in a format that is ready for printing via a dot matrix printer. For reference I have also attached an example of what the resultant text file should look like.
ConcertTickets.txt and
ConcertTickets_result.txt
My major problem is architecting an approach to this problem. I can’t figure out how to print column by column. I was able to read the file, print row by row, do the validation and write the file with a new name. I’m not sure how to do the layout_name, columns, column_width, column_spacing, left_margin, row spacing and line_item, the best I could do was ljust() for the left margin between the tickets.
I don’t expect someone to do the work for me, but would greatly appreciate tips on architectural approaches with and without third party packages.
The input concert ticket file consists of a header containing formatting information and a body containing the actual tickets.
The header lines are as follows:
download_datetime - the date and time the file was downloaded
order_datetime - the date and time the order for the tickets were placed
layout_name - the name of the layout used for formatting the tickets
columns - the number of columns of tickets per page width
column_width - the width of each ticket column
column_spacing - the number of spaces between ticket columns
left_margin - the leading space to the left of the first ticket column
row_spacing - the number of horizontal lines between tickets
line_item - the line items represent how the ticket elements must appear in the
ticket, e.g. the PIN at the top, followed by two empty lines, then the description, serial number and expiry date. Valid values for line items are: pin, description, serial_number, expiry_date and empty (space)
ticket_summary - Each ticket summary contains the ticket description followed by the number of ticket of that type in the file and the total face value of the ticket, e.g. "Gold 10.00,10,100.00" means there are 10 Gold $10.00 tickets to the value of $100.00 in the file
ticket_fields - the ticket fields indicate the fields and their order that are present in the ticket data that follows. This is the last line of the header and all data that follows this line should be interpreted as body data, i.e. the actual tickets in a CSV type format
The script also needs to do some basic file validation by checking that the number of actual tickets in the body of the file match the ticket summary values in the header of the file. If file validation fails the program must exit with an appropriate error message.
The resultant output file name must be the same as the input file name, but with the word "_result" appended to it just before the file extension. E.g. if the input file name is ConcertTickets.txt then the output file name must be ConcertTickets_result.txt
I also need to develop a set of test cases for the script.
This is my code thus far
data = []
data_description = []
data_pin = []
data_serial_number = []
data_expiry_date = []
tickets_in_body = 0
# read file from line 19 and create two-dimensional array
result_f = open('ConcertTickets.txt')
for each_line in result_f.readlines()[18:]:
(description, pin, serial_number, expiry_date) = each_line.split(',')
data_description.append(description)
data_pin.append(pin)
data_serial_number.append(serial_number)
data_expiry_date.append(expiry_date.replace("\r\n",""))
tickets_in_body += 1
data = [data_description, data_pin, data_serial_number, data_expiry_date]
# ticket validation and writing to file
result_golden_summary = open('ConcertTickets.txt')
golden_summary = result_golden_summary.readlines()
(golden_description, golden_summary_amount, golden_summary_value) = (golden_summary[15 - 1]).split(',')
if int(golden_summary_amount) != tickets_in_body:
print('The ticket summary in the header does not match the amount of tickets in body')
else:
(filename, extension) = (result_f.name).split('.')
result_f = open(filename + "_result.txt", 'w')
for row in data:
result_f.write("".join(str(item).ljust(25) for item in row))
result_f.close()
here's some code for you:
import math
result_f = open('ConcertTickets.txt')
all_lines_arr = []
for each_line in result_f.readlines()[18:]:
(description, pin, serial_number, expiry_date) = each_line.split(',')
line_dict = {}
line_dict["description"] = description
line_dict["pin"] = pin
line_dict["serial_number"] = serial_number
line_dict["expiry_date"] = expiry_date.strip()
all_lines_arr.append(line_dict)
per_row = 5
line_space = 30
rows = math.ceil(len(all_lines_arr)/per_row)
for i in range(0, rows):
row_val = (i*per_row)+per_row
if (row_val > len(all_lines_arr)):
row_val = row_val - (row_val-len(all_lines_arr))
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["pin"] + (line_space-(len(all_lines_arr[j]["pin"]))%line_space)*" ", end="")
print("\n"*2)
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["description"] + (line_space-(len(all_lines_arr[j]["description"]))%line_space)*" ", end="")
print()
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["serial_number"] + (line_space-(len(all_lines_arr[j]["serial_number"]))%line_space)*" ", end="")
print()
for j in range((i*per_row), row_val):
print(all_lines_arr[j]["expiry_date"] + (line_space-(len(all_lines_arr[j]["expiry_date"]))%line_space)*" ", end="")
print("\n"*5)
First we read the lines, and put them into an array of dictionaries i.e. each array element is a dictionary, which has an addressable value e.g. description
Next, we use per_row to decide how many tickets to print per row (you can change this).
Then the code will print the dictionary values for each element in the array.
The key to the formatting is that it uses modulus % to print the correct number of spaces. I used 30 as the separator.
I stripped out a lot of your code in order to just do the print formatting for you. It will be up to you to modify this to print to file or do anything else you need it to.
It is a bit too hardcoded for my liking, but without knowing more about exactly what you need, it works for your simple case.
Hope this helps!
This is the recomended way to open (and close) a file:
# open file as read ('r')
with open('ConcertTickets.txt', 'r') as file:
for line in file.readlines()[18:]:
# your logic
# open result file as write ('w'), '+' creates the file if not exist
with open('ConcertTickets_result.txt', 'w+' as file:
# your logic
still learning python, so I apologize if this question is sloppy.
I am familiar with loops, and looping through a file. However, I have not found the correct referance to looping a file, storing the variable and calling that variable into another function, and maintain the increment.
Using pyautogui and pywinauto.
Written form:
get names.txt file with list of 20 or so names (the list changes so keeping track of line count seems reasonable)
Split the text of the file for parsing.
in example:
setup of name.txt file.
Mark
James
Sam
Steve
.
def do(name):
# open and read file
fname = 'names.txt'
for name in (open(fname, "r")).readlines():
print("Found: " + name)
more(name)
Output:
['Mark', 'James', 'Sam', 'Steve]
def more(name):
pyautogui.moveT0(600,511)
pyautogui.click()
pyautogui.typewrite(a[0])
pyautogui.moveTo(699,412)
pyautogui.press("enter")
confirm(name)
def confirm(name)
pic = pyscreenshot.grab(bbox=(8,11,211,728))
f = "images/active"
g = "images/go"
pic.save(f + a + ".png")
pic.save(g + ".png")
b = Image.open("images/go.png"
text = image_to_search(b, lang='eng')
if text == name:
print("Success")
else:
print("Mismatch")
This is the part where the function will end and start back at the top of the program increment our digit and applying the next name for searching. The confirm program (already completed) takes an image of the search field and passes the text. If the name is equal to the name in the list (a[0]) then we move onto the next name.
Bringing up another question of how to "call a variable from a function"?
Thanks a lot!
First off, your code is rife with indentation, syntactical and logcial errors, you have to fix those before you apply the below
def file_stuff(a, fname):
for name in (open(fname, "r")).readlines():
print ("Found: " + name)
gui_stuff(name)
def gui_stuff(name):
pyautogui.moveT0(600,511)
pyautogui.click()
pyautogui.typewrite(name) # ATTENTION, please confirm if this is how the typewriter fn works. you are only printing the first char
pyautogui.moveTo(699,412)
pyautogui.press("enter")
confirm(name)
Please fix the if-else indentation in your confirm function, and other dangling indentation references in your code