how to delete a line from a txt file using python? - python

I have a file with data about students such as their name, address, grades, etc. I created a function that would delete a whole line from a text file based on a student's First Name and Last Name. This function worked correctly. However, afterward, I decided to update it so that if the user entered a name that was not in the file it would print: Student not found. However, now even, if the user types in a name that is in the file it still prints: student not found...
Here is my code:
def delete_a_record(filename):
x=input("Remove First Name:")
y=input("Remove Last Name:")
with open(filename, "r") as f:
lines = f.readlines()
with open(filename, "w") as f:
for i in lines:
t=i.split()
if t[0]!=x and t[1]!=y:
f.write(i)
elif x or y not in t:
print("Student Not Found")
f.close()
delete_a_record("mytextfile.txt")
Could someone explain to me why?

For what I undestood(correct me if I'm wrong), I guess there is two issues in your logic.
If you mean to test if both x and y are not in t you should test it separatelly, like:
if t[0]!=x and t[1]!=y:
f.write(i)
elif x not in t and y not in t:
print("Student Not Found")
The way it is now, if x is not None, the condition elif x or ... will always return true because x evaluates to True.
If you want to check if the student is not in the entire file, I think you should not be testing this for each line you read. Since you don't know in which line the student might be, maybe you could reorganize your code to process the whole file first before testing if the student was not found.

Probably because you are iterating line by line, so even if the name is in the .txt file every time the name doesn't match the current line it will print "Student Not Found". You need to rewrite you function so that the print statement is only made when the lines have been exhausted and the name has not been found.

If You Want to Use Your Function And Search In That (You Don't Want to Change Your Function) You Can Put Your Data In A List And Search In That List Like Below Code:
list=['f_Name = Lorem','l_Name = Ipsum']
if "f_Name = "+x in list or "l_Name = "+y in list:
print("True")
else:
print("Student Not Found")

Related

Why does python delete every line except the first one?

I have a text file with some data in it, and i've written a code that is supposed to delete a specific line when te if statement is true. Why does python delete every line except the first one? And how do i fix it?
def give_back():
number_input = input('What is ur number?')
code_input = input('Enter the code corresponding to your number.')
b = [f'{number_input};{code_input}']
with open('fa_kluizen.txt', 'r') as f:
x = f.readlines()
with open('fa_kluizen.txt', 'w') as f:
for line in x:
if line.strip('\n').strip() != b:
f.write(line)
return True
else:
return False
You have two basic issues. The first is the way you handle your loop:
def give_back():
...
return True # leaves the function `give_back`
Even though you have a for line in x between these two statements, it will only ever run the first loop because you use the keyword return. This leaves the function. If you expect more work to be done, you need to avoid doing this.
Secondly, you are using the read-write flags awkwardly. When you open a file with open('somefile.txt', 'w') it opens for writing, truncating (deleting the contents of) the file first. If you plan to write every line back, that is fine, but since your loop only occurs once, the first line will be all that is in the file when you're done.
You don't say what you want the actual end result to look like with a given input, so it's impossible to say what the correct way to fix this is, but I'd start by getting rid of your return statements and see whether that matches what you're looking for.
You probably meant something like this:
def give_back():
number_input = input('What is ur number?')
code_input = input('Enter the code corresponding to your number.')
b = [f'{number_input};{code_input}']
with open('fa_kluizen.txt', 'r') as f:
x = f.readlines()
with open('fa_kluizen.txt', 'w') as f:
for line in x:
if line.strip('\n').strip() != b:
f.write(line)
The problem is that if u return the function exits

How to read IDs from a .txt file?

I'm doing a database using txt files in which the data is stores like this: idTheme|Name|Hours.
For example: 45|Object Oriented Programming|12
I need to print the line of text with the idTheme I'm given, so I did this:
print("Give me the ID")
id_search = input("> ")
for line in file:
for x in line:
if id_search != x:
break
else:
print(line)
break
Since the ID is always the first character in each line I thought thst would work.
Problem is, this only works when the ID is 1 character long.
I was thinking on putting the info on a list and using a split("|") to divide it but that would put all the info in the list, not only the IDs.
Any suggestions are apreciated.
You could use split as you said and just use index 0 to get the ID.
for line in file:
id = line.split("|")[0]
if id_search == id:
print(line)
You can invert your if statement so if the id is equal to the search term it prints the line, otherwise nothing happens. You also avoid looping through the entire line.
You can use somethign like:
with open("text.txt") as f:
lines = [x.strip() for x in list(f) if x]
print("Give me the ID")
id_search = input("> ").strip()
if id_search:
for line in lines:
id, name, otherid = line.split("|")
if id_search == id:
print(line)
break
Demo

Code to print corresponding CSV/list values for car program is not printing anything at all

I have tried to get help on this question all day, but none of the already-asked questions have solved my problem, and any answers I have asked to help me solve this problem have resulted in answers that didn't answer the question.
As it stands now, my program takes the values of MPG ratings represented in a CSV and puts them in a list. These lists represent maximum and minimum MPGs. Once the max/min MPG rating is found is where I get into my problem. I need to be able to print all the cars that have the minimum/maximum MPG value. Ideally, the models should be printed indented under the print statements for the maximum/minimum mileage ratings.
The way the CSV file is done the MPG ratings are in column 9 (index[8]). The make and models are in columns 2 and 3, respectively (index[1] and index[2], respectively). As you'll see in the code, I tried looping through the list and using an if statement to pull the make/model, but when I do that it does not work. I don't know if the files play a part or not, but any help would be appreciated.
# prints welcome screen, asks user what year they want vehicle data for, and asks user for file name to save vehicle data to
print("Welcome to EPA Mileage Calculator")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
while yearChoice != 2008 and yearChoice != 2009:
print("Invalid input, please try again")
yearChoice = int(input("What year would you like to view data for? (2008 or 2009): "))
saveResults = input("Enter the filename to save results to: ")
def carData():
if yearChoice == 2008:
fileName = "epaVehicleData2008.csv"
elif yearChoice == 2009:
fileName = "epaVehicleData2009.csv"
fileIn = open(fileName, "r")
fileIn.readline()
minMPG = []
maxMPG = []
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[0] not in ['VANS - PASSENGER TYPE', 'VANS - CARGO TYPE', 'TRUCK', 'MINIVAN - 4WD', 'MINIVAN - 2WD']:
minMPG.append(int(dataList[8]))
maxMPG.append(int(dataList[8]))
maximumMPG = max(maxMPG)
minimumMPG = min(minMPG)
fileOut = open(saveResults, "w")
print("EPA City MPG Calculator", "(" + str(yearChoice) + ")", file=fileOut)
print("---------------------------------", file=fileOut)
print("Maximum Mileage (city):", maximumMPG, file=fileOut)
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[8] == maximumMPG:
print("\t", dataList[1], dataList[2], file=fileOut)
print("Minimum Mileage (city):", minimumMPG, file=fileOut)
for line in fileIn:
line = line.strip()
dataList = line.split(",")
if dataList[8] == minimumMPG:
print("\t", dataList[1], dataList[2], file=fileOut)
fileIn.close()
fileOut.close()
def complete():
print()
print("Operation Success! Mileage data has been saved to", saveResults)
print("Thanks, and have a great day!")
def main():
carData()
complete()
main()
You open the input file only once via:
fileIn = open(fileName, "r")
But then you attempt to iterate over the lines in the file three times using that same file handle. You have three of these:
for line in fileIn:
Since you never close and reopen the file, and you don't do anything to seek back to the beginning of the file, the second and third such iterations will never do anything, because you've already reached the end of the file. Using this construct does not cause the file pointer to be rewound and the contents of the file to be iterated over another time.
Since your interesting print statements are in the second and third iterations over the file, which won't produce any new lines (the code in those iteration blocks will never be called), of course your print statements are never called and no output is generated.
To fix your problem, if this is the only thing wrong with your code, just put this line before each of the second and third iterations over the file:
f.seek(0)
to seek back to the beginning of the file and iterate over the contents a second and third time.
To be more efficient, you could read each line once and store it in a list. Then you could iterate over the list each time, and not have to read from the file three times. You could even do the strip and the split just once, making the code even more efficient.
Another small logic error that I see is that you skip one line in your first iteration over the file. I assume that this is to skip a header row at the start of the file. But you don't do this for the second and third iterations, so it seems that if you only add the seek() as I suggested, you'll be trying to process the header line as a data line. This would also be solved by reading the file once into a list. You'd skip the first line of the file while you do this. If you want to leave the code alone other than adding the seek(), you should also skip the first line before the second and third iterations.

How to print a specific line from a file

I am trying to print a specific line from the file "Scores", which is option B. This is my code:
print("Option A: Show all scores\nOption B: Show a record\nOption Q: Quit")
decision = input("Enter A, B, C or Q: ")
myFile = open("Scores.txt", "rt")
if decision == "A":
record = myFile.read()
print(record)
myFile.close()
elif decision == "B" or decision == "b":
playerName = input("Enter a player name to view their scores: ")
record = myFile.read()
answer = record.find(playerName)
for line in answer:
print(line)
elif decision == "Q" or decision == "q":
exit
I went for Option B, then I entered a player name that holds the score of the player, but it throws this error message:
line 12, in <module>
for line in answer():
TypeError: 'int' object is not callable
A few cents from my side :
file = open("file")
lines = file.readlines()
for line in lines:
if playername in line:
print line
file.close()
Hope it works!
find() method returns a positive index if it succeeds, -1 otherwise
You should loop on your content line by line, as follows:
for line in myFile:
if line.find(playerName):
print(line)
A safer way to read the file and find data, so that you will not have OutOfMemory issues when storing the whole file in memory.
playerName = input("Enter a player name to view their scores: ")
with open("Scores.txt", 'r') as f:
for row in f:
if playerName in row:
print row
This way you will be using with that will close the file by itself either when the program ends or Garbage Collection kicks in. This way python will read the file line by line and store only 1 line in memory. So you can use huge files and do not worry about memory issues.
Hope it helps :)
Working with str methods will take more acrobatics. Try the following,
import re
p = re.compile(r"\b{}\b".format(playername)) # keep it ready
# inside option B
for line in myfile: # no need to `.read()` it
match = p.search(line)
if match:
print(line)
break # if there is only one record for playername
See if it works for you.
similar thing here:
Reading specific lines only (Python)
fp = open("file")
for i, line in enumerate(fp):
if line == playername:
print line
fp.close()
I also notice you don't close your file for each decision, should make that happen.
Few python idioms and small optimization
Here are many answer, my sample brings in few python idioms and optimize it a bit:
fname = "Scores.txt"
player_name = "Quido"
with open(fname) as f:
for line in f:
if player_name in line:
print line
break
print "Going on doing following tasks."
The with block will close the open file on exiting the inner block. No need to f.close(), safe
in case of problems to read the file.
for line in f: shows, that iterating over file open in text mode we get one line per iteration.
break after we print the line with the player will effectively stop iterating over lines assuming,
there is only one such line or that we are happy with the very first one. If this is not the case,
removing the break allows printing all lines containing the player name.
As lines returned from text file iterator contain new line, you may prefer to get rid of them. Use
print line.strip() in such case what will remove all blank characters from start and end of the line.
Final print is proving, the program continues after it processes all the lines.
It may happen, that you get no output for name, which appears to be present in the file. In such a
case, you might need to clarify letter case. For example, if your text file contains all the names
in exact casing, you have to enter the name properly.
Other option is to lower-case the player_name and compare it against lower cased line:
fname = "Scores.txt"
player_name = "Quido"
normalized_player_name = player_name.lower()
with open(fname) as f:
for line in f:
if normalized_player_name in line.lower():
print line.strip()
break # comment out to print all lines with the player
print "Going on doing following tasks."
Note, that we normalize the player_name outside from the loop to be a bit faster. Lower-casing inside the
loop would work, but would do the same task repeatedly.
The line is printed using exact letter cases as in the file.

Adding user data into rows python

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

Categories

Resources