Why does python delete every line except the first one? - python

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

Related

For loop only returns first line of textfile

I am trying to make a program where i have to check if certain numbers are in use in a text file. The problem is that my for loop only loops trough the first line, instead of every line. How can i solve this? I've already used readlines() but that has not worked for me. This is the code and i've got a text file with: 1;, 2; and 3;, each on a seporated line. Hope someone can help!
if int(keuze) == 2:
def new_safe():
with open('fa_kluizen.txt', 'r') as f:
for number in f:
return number
print(new_safe())
My text File:
# TextFile
1;
2;
3;
You are returning too early (at first iteration).
You can read all lines in a list while cleaning the data and then return that list.
with open('fa_kluizen.txt', 'r') as f:
data = [line.strip() for line in f]
return data
Also most of the time its bad to create a function inside an if-statement.
Maybe you can add a little bit more information about what you want to achieve.
you are returning the first line you encounter, and by doing so, the program exits the current function and of course, the loop.
One way to do it is:
def new_safe():
with open('fa_kluizen.txt', 'r') as f:
return f.read().splitlines()
Which returns a each line as a list of the strings.
Output:
['1;', '2;', '3;']
That's beacause "return numbrer", Try
if int(keuze) == 2:
def new_safe():
my_list = []
with open('fa_kluizen.txt', 'r') as f:
for number in f:
my_list.append(number)
return my_list

how to delete a line from a txt file using 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")

Search for string and delete line that contains string and the line underneath

I have a text file that contains
### 174.10.150.10 on 2018-06-20 12:19:47.533613 ###
IP : 174.10.150.10 :
IP : ALL :
I currently have code that uses Regex to search for a date/time string.
How can I delete a line that contains the string that I find? I want to delete that line and also the line underneath.
So both of these lines would get deleted:
### 174.10.150.10 on 2018-06-20 12:19:47.533613 ###
IP : 174.10.150.10 :
My code currently just adds 'None' to the bottom of the text file.
import re
def run():
try:
with open('file.txt', 'r') as f:
with open('file.txt', 'a') as f2:
reg = re.compile('###\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.+(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.\d{0,})\s###')
for line in f:
m = reg.match(line)
answer = raw_input("Delete line? ")
if answer == "y":
# delete line that contains "###" and line underneath
f2.write(str(m))
else:
print("You chose no.")
except OSError as e:
print (e)
run()
(EDIT: I now understand from your comments that you have a blank line after two data lines, so when you want to delete a line you also want to delete the next two lines. My code has been adjusted to do that.)
Here is some code, making various changes to your code. I wrote a new file rather than overwriting the old file, for safety and to avoid needing to keep the entire file in memory at once. I combined the with lines into one line, for readability; similarly, I split the regex string to allow shorter lines of code. To avoid having more than one line in memory at once, I used a countdown variable skipline to note if a line is to be skipped in the new file. I also show each line before asking whether or not to delete it (with its following line). Note that lines that do not have the date and time are copied, by checking that the regexp match variable is None. Finally, I changed raw_input to input so this code will run in Python 3. Change it back to raw_input for Python 2.
By the way, the reason your code just adds 'None' to the end of the file is that you put your write line outside the main loop over the lines of the file. Thus you write only the regex match object for the last line of the file. Since the last line in your file does not have a date and time, the regex did not match so the string representation of the failed match is 'None'. In your second with statement you opened file.txt in append mode, so that 'None' is appended to the file.
I want to emphasize that you should create a new file. If you really want to overwrite the old file, the safe way to do that is to create a new file first with a slightly different name. Then if that file is made successfully, overwrite the old file with the new file and rename one copy to something like file.bak. This takes possible OS errors into account, as your code attempts to do. Without something like that, an error could end up deleting your file completely or mangling it. I leave that part of the code to you.
import re
def run():
try:
with open('file.txt', 'r') as f, open('file.tmp', 'w') as f2:
reg = re.compile('###\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
'.+(\d{4}-\d{2}-\d{2}\s\d{2}'
':\d{2}:\d{2}.\d{0,})\s###')
skipline = 0 # do not skip lines
for line in f:
if skipline:
skipline -= 1
continue # Don't write or process this line
m = reg.match(line)
if m:
answer = input("Delete line {} ? ".format(m.group()))
if answer == "y":
skipline = 2 # leave out this and next 2 lines
else:
print("You chose no.")
if not skipline:
f2.write(line)
except OSError as e:
print(e)
run()
I refactor the filtering part into a function called filter_lines and move the regex as module variable. This approach make use of iterator.
import re
regex = re.compile('###\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.+(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.\d{0,})\s###')
def filter_lines(lines):
it = iter(lines)
try:
while True:
line = next(it)
m = regex.match(line)
if m:
# You may add the question-answer code here to ask the user whether delete the matched line.
next(it) # Comsume the line following the commented line
continue
yield line
except StopIteration:
# In the future, StopIteration raised in generator function will be converted to RuntimeError so it have to be caught.
# https://www.python.org/dev/peps/pep-0479/
pass
def run():
try:
with open('file.txt', 'r') as f:
with open('file.txt', 'a') as f2:
filtered_lines = list(filter_lines(f1.readlines()))
print(*filtered_lines, sep='')
# You may use the following line to actually write the result to a file
# f2.writelines(filtered_lines)
except OSError as e:
print (e)
run()
This program should print the resultant content.
With some basic refactoring, here's the result...
import re
valid_lines = []
def run():
try:
with open('file.txt', 'r') as f:
reg = re.compile('###\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.+(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.\d{0,})\s###\s?')
lines = f.readlines()
invalid_index = -10
for a in range(len(lines)):
reg_result = reg.match(lines[a])
if invalid_index == (a - 1):
# Skip the line underneath the invalid line
continue
if reg_result != None:
# If the line matches the regexp.
invalid_index = a
answer = raw_input("Delete line? ")
if answer.lower() != 'y':
print("You chose no.")
valid_lines.append(lines[a])
else:
valid_lines.append(lines[a])
with open('file.txt', 'w') as f:
# Override the file...
f.writelines(valid_lines)
except OSError as e:
print (e)
run()
If you want to remove any lines that start with ### then, maybe you should consider this as the regexp: ###.*
EDIT: In your regular expression, you should add a \s? at the end to optionally match \n, as the file contains newlines. Also, use fullmatch() instead of match().

Struggling to get a simple function running from command line

I'm trying to get the below function running from the command line by simply using
python filename.py
However, it isn't doing what I want.
Could someone please help me out with this? I'm sure I'm missing something very simple...
inFile = ""
inFile = raw_input("Enter the File Name: ")
x = open(inFile, 'w')
def summation(x):
sum = 0
for i in x:
sum = sum + i
return sum
if __name__ == "__main__":
print(summation(x))
Hopefully it's fairly self explanatory what I'm trying to achieve, but in case it's not...
I'm asking for a raw_input; this will be a text file full of numbers (each on it's own line). The file should be fed into the variable x which is then used in the summation function. Finally, with a for loop each value is summed and the sum is returned (and printed in terminal).
There are two problems:
You're opening the file in write mode. This deletes all the contents of the file. Drop the "w" parameter.
You can't add strings (as read from the file) to an integer. You need to convert them to integers first: sum += int(i)
Also, you should close the file after you've read its contents. And the line infile = "" is unnecessary.
A more pythonic version...
def line_to_int(line):
line = line.strip()
if not line:
# handles the case of empty lines
return 0
return int(line)
def sumfile(f):
return sum(line_to_int(line) for line in f)
if __name__ == "__main__":
fname = raw_input("Enter the File Name: ").strip()
with open(fname) as f:
print(sumfile(f))
or even more simple as long as you don't plan on adding error handling around the call to int(line) (thanks Jon Clements):
if __name__ == "__main__":
fname = raw_input("Enter the File Name: ").strip()
with open(fname) as f:
print(sum(int(line.strip() or 0) for line in f))

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.

Categories

Resources