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.
Related
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
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().
I'm really desperate for some help on this python code please. I need to search for a variable (string), return it and the data present on the same line as the variable data.
I've managed to create a variable and then search for the variable in a text file, however if the data contained in the variable is found in the text file the contents of the whole text file is printed out not the line in which the variable data exists.
This is my code so far, please help:
number = input("Please enter the number of the item that you want to find:")
f = open("file.txt", "r")
lines = f.read()
if lines.find("number"):
print (lines)
else:
f.close
Thank you in advance.
See my changes below:
number = input("Please enter the number of the item that you want to find:")
f = open("file.txt", "r")
lines = f.read()
for line in lines: # check each line instead
if number in line: # if the number you're looking for is present
print(line) # print it
It goes like
lines_containg_number = [line for line in lines if number in line]
What this'll do is give you all the lines in the text file in the form of a list and then you can simply print out the contents of the list...
If you use 'with' loop, you don't have to close file. It will be handled by with. Otherwise you have to use f.close(). Solution:
number = input("Please enter the number of the item that you want to find:")
with open('file.txt', 'r') as f:
for line in f:
if number in line:
print line
I am trying to read in every line in a file that starts with an 'X:'. I don't want to read the 'X:' itself just the rest of the line that follows.
with open("hnr1.abc","r") as file: f = file.read()
id = []
for line in f:
if line.startswith("X:"):
id.append(f.line[2:])
print(id)
It doesn't have any errors but it doesn't print anything out.
try this:
with open("hnr1.abc","r") as fi:
id = []
for ln in fi:
if ln.startswith("X:"):
id.append(ln[2:])
print(id)
dont use names like file or line
note the append just uses the item name not as part of the file
by pre-reading the file into memory the for loop was accessing the data by character not by line
for line in f:
search = line.split
if search[0] = "X":
storagearray.extend(search)
That should give you an array of all the lines you want, but they'll be split into separate words. Also, you'll need to have defined storagearray before we call it in the above block of code. It's an inelegant solution, as I'm a learner myself, but it should do the job!
edit: If you want to output the lines, simply use python's inbuilt print function:
str(storagearray)
print storagearray
Read every line in the file (for loop)
Select lines that contains X:
Slice the line with index 0: with starting char's/string as X: = ln[0:]
Print lines that begins with X:
for ln in input_file:
if ln.startswith('X:'):
X_ln = ln[0:]
print (X_ln)
Hopefully this is an easy fix. I'm trying to edit one field of a file we use for import, however when I run the following code it leaves the file blank and 0kb. Could anyone advise what I'm doing wrong?
import re #import regex so we can use the commands
name = raw_input("Enter filename:") #prompt for file name, press enter to just open test.nhi
if len(name) < 1 : name = "test.nhi"
count = 0
fhand = open(name, 'w+')
for line in fhand:
words = line.split(',') #obtain individual words by using split
words[34] = re.sub(r'\D', "", words[34]) #remove non-numeric chars from string using regex
if len(words[34]) < 1 : continue # If the 34th field is blank go to the next line
elif len(words[34]) == 2 : "{0:0>3}".format([words[34]]) #Add leading zeroes depending on the length of the field
elif len(words[34]) == 3 : "{0:0>2}".format([words[34]])
elif len(words[34]) == 4 : "{0:0>1}".format([words[34]])
fhand.write(words) #write the line
fhand.close() # Close the file after the loop ends
I have taken below text in 'a.txt' as input and modified your code. Please check if it's work for you.
#Intial Content of a.txt
This,program,is,Java,program
This,program,is,12Python,programs
Modified code as follow:
import re
#Reading from file and updating values
fhand = open('a.txt', 'r')
tmp_list=[]
for line in fhand:
#Split line using ','
words = line.split(',')
#Remove non-numeric chars from 34th string using regex
words[3] = re.sub(r'\D', "", words[3])
#Update the 3rd string
# If the 3rd field is blank go to the next line
if len(words[3]) < 1 :
#Removed continue it from here we need to reconstruct the original line and write it to file
print "Field empty.Continue..."
elif len(words[3]) >= 1 and len(words[3]) < 5 :
#format won't add leading zeros. zfill(5) will add required number of leading zeros depending on the length of word[3].
words[3]=words[3].zfill(5)
#After updating 3rd value in words list, again creating a line out of it.
tmp_str = ",".join(words)
tmp_list.append(tmp_str)
fhand.close()
#Writing to same file
whand = open("a.txt",'w')
for val in tmp_list:
whand.write(val)
whand.close()
File content after running code
This,program,is,,program
This,program,is,00012,programs
The file mode 'w+' Truncates your file to 0 bytes, so you'll only be able to read lines that you've written.
Look at Confused by python file mode "w+" for more information.
An idea would be to read the whole file first, close it, and re-open it to write files in it.
Not sure which OS you're on but I think reading and writing to the same file has undefined behaviour.
I guess internally the file object holds the position (try fhand.tell() to see where it is). You could probably adjust it back and forth as you went using fhand.seek(last_read_position) but really that's asking for trouble.
Also, I'm not sure how the script would ever end as it would end up reading the stuff it had just written (in a sort of infinite loop).
Best bet is to read the entire file first:
with open(name, 'r') as f:
lines = f.read().splitlines()
with open(name, 'w') as f:
for l in lines:
# ....
f.write(something)
For 'Printing to a file via Python' you can use:
ifile = open("test.txt","r")
print("Some text...", file = ifile)