I was just wondering if I can make a simple script that searches for different strings on user input. Let's say I want to search first time for word "apple" and the second time "orange" and to display all the lines where apples and oranges exist. I want first to be indipendent from the second search.
`string = "start"
while string != "end":
string = input('Enter fruit: ')
print("looking for ",string )
for line in f:
if "Started" and string in line:
print("debug")
print(line)`
What this does is works first time and doesn't the second time. I am prompted after the output to enter another fruit but instead of presenting all the lines where the fruit is found it just prompts with another request to enter a fruit.
Assuming you have some line like f = open('BigTextFileFullOfFruit.txt', 'r') above the snippet you posted:
You can only iterate once over a file. You have to call f.seek(0) to go over it again.
This is because f is an iterator and it cannot be consumed more than once. After that it is exhausted and will not yield anymore.
To go around this, you may seek to the beginning to re-iterate or save the contents in a list for reuse.
# Put this inside your outermost loop
string = raw_input("Enter string: ")
f = fp.readline()
while f:
if f.find(string) >= 0 and "Started":
print(f, end=' ')
f = fp.readline()
Related
So I am trying to make a game where the 'GameMaster' picks the first word from a .txt file, then the user tries to guess the word. Once the user correctly guess the word, the GameMaster looks to the next line in the file and the user has to guess again, so on and so forth...
The problem I am having, is getting the program to assign variables as the game continues. The program should iteratively look until there are no more words to choose from, whether that be 2 or infinity.
Since I don't have much experience working with file interaction in python, the best example I have is something like this:
file "input.txt" will contain:
dog
cat
bird
rat
mouse
And I am looking at what in in the .txt file with this:
def file_read():
with open ('/Users/someone/Desktop/input.txt', 'r') as myfile:
data = myfile.read()
for line in data:
line.rstrip()
return data
Your function returns the entire contents of the file, unaltered. myfile.read() returns the data from the file as a string. The for loop then iterates over every character in that string, not the lines. Furthermore, rstrip() operates only on each character. It does not affect the contents of data because data is an immutable string and the return value of rstrip() is not stored anywhere.
Something like this would better suit:
def file_read():
with open('/Users/someone/Desktop/input.txt') as myfile:
return [line.rstrip() for line in myfile]
This will return a list of the stripped lines from the file. Your word guessing code would then iterate over the list.
The above will work, however, it is not very efficient if the input file is large because all of the file would be read into memory to construct the list. A better way is to use a generator which yields a stripped line one at a time:
def file_read():
with open('/Users/someone/Desktop/input.txt') as myfile:
for line in myfile:
yield line.rstrip()
Now that function is so simple, it seems pointless to bother with it. Your code could simply be:
with open('/Users/someone/Desktop/input.txt') as myfile:
for line in myfile:
user_guess_word(line.rstrip())
where user_guess_word() is a function that interacts with the user to guess what the word is, and returns once the guess it correct.
This way uses readlines to get file contents in a list line by line. readlines returns a list containing lines.
Now iterate through list to check if user input matches with line content (which is a word in this case).
with open ('/Users/someone/Desktop/input.txt', 'r') as myfile:
words = myfile.readlines()
while x < len(words):
if words[x] == input('Enter word to guess'):
print('Predicted word correctly')
else:
print('Wrong word. Try again')
x -= 1
x += 1
You can do it like,
def fun():
data = open('filename', 'r').readlines()
user_guess, i = None, 0
while i < len(data):
user_guess = input()
if user_guess not None and user_guess == data[i]:
i = i + 1
Please trim() / strip() also while you compare user_guess and data[i]
I have this code, what I want it to do is take a user input of something like:
1
2
3
4
5
And turn it into: 1, 2, 3, 4, 5
My code doesn't seem to do it, it just returns the first word in the list, any help would be amazing.
i = raw_input("Put the list here: ")
print (i.replace("\r", ", "))
I changed the format, it will now pull the input from a text file, this seems to work as long as each line is only seperated by a single line break
i = open("input.txt", "r")
o = open("output.txt", "w")
for line in i.readlines():
o.write (line.replace("\n", ", "))
i.close()
o.close()
When the user press enter after the 1 raw_input stops reading.
Take a look at this question to see how to read multiple lines
Raw input across multiple lines in Python
You can write a simple loop and break with some specified command. For example
break_command = 'q'
values = []
while True:
i = raw_input("Type a number (or q to exit): ")
if (i==break_command): break
values.append(i)
If you want to take multiple user inputs, put all the inputs into a list, and then print out the list, try this:
listX = [] #An empty list
for x in range(y): #Where y in the number of times you want the user to enter the input
listX.append(raw_input("Your message here: "))
print listX
If you want to to print out the members of the list without the square brackets, you could convert the list into a string:
listX = str(listX)
Following this, since the square brackets constitute the first and last characters of the string only, implement the following command:
listX = listX[1:-1]
Of course, it is possible to implement the previous two commands simultaneously:
listX = str(listX)[1:-1]
However, note that the final value of listX is of type string. If you require this value as in int, replacing the line:
listX.append(raw_input("Your message here: "))
with:
listX.append(int(raw_input("Your message here: ")))
and simply printing out the list may be a more efficient, if not better, option.
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.
So I am trying to store a single word to a file (which i have already managed to figure out how to do). The program would then repeat and ask me to input another word. It should check if this word already exists in the file (which it should). I have it to the point where i have inputted a word and it has stored it in the file but when i input the same word again it doesn't realise that the word already exists in the file. (This is all in a def function so when i say the next time it goes round i mean the next time i call the function)
Here is the code:
def define():
testedWord = subject
lineNumber = 1
lineInFile = "empty"
exists = False
while lineInFile != "":
wordsFile = open("Words.txt", "a")
lineInFile = linecache.getline("Words.txt", lineNumber)
lineNumber = lineNumber + 1
lineInFile = lineInFile.replace("\n", "")
if lineInFile == subject:
definitionNumber = lineNumber
exists = True
if exists == False:
wordsFile.write(testedWord)
wordsFile.write("\n")
wordsFile.close()
subject = input("")
define()
##This whole thing basically gets repeated
Like i said, if i store a new word and then in the same program try and put in the same word again then it won't recognize that it has already stored this word. When i stop the program and restart it, it works (but i dont want to have to do that)
Thanks for you help (if it is possible to help lol)
Dan
I think you're making (almost) everything more complicated than it needs to be. Here is a different way of doing what you're trying to do:
def word_check(f_name, word):
with open(f_name) as fi:
for line in fi: # let Python deal with line iteration for you
if line.startswith(word):
return # return if the word exists
# word didn't exist, so reopen the file in append mode
with open(f_name, 'a') as fo:
fo.write("{}\n".format(word))
return
def main():
f_name = "test.txt"
with open(f_name, 'w') as fo:
pass # just to create the empty file
word_list = ['a', 'few', 'words', 'with', 'one',
'word', 'repeated', 'few'] # note that 'few' appears twice
for word in word_list:
word_check(f_name, word)
if __name__ == "__main__":
main()
This produces an output file with the following text:
a
few
words
with
one
repeated
In this example, I just created a list of words instead of using input to keep the example simple. Note how inefficient your current method is, though. You're reopening a file and reading every line for every word entered. Consider building your word list in memory instead, and writing it out at the end. Here's an implementation that takes advantage of the built-in set datatype. They don't allow repeated elements. If you're okay with writing out the file at the end of the program run instead of on-the-fly, you can do this instead:
def main():
word_set = set()
while True:
word = input("Please enter a word: ")
if word == 'stop': # we're using the word 'stop' to break from the loop
break # this of course means that 'stop' should be entered
# as an input word unless you want to exit
word_set.add(word)
with open('test.txt', 'w') as of:
of.writelines("{}\n".format(word) for word in word_set)
# google "generator expressions" if the previous line doesn't
# make sense to you
return
if __name__ == "__main__":
main()
Printed output:
Please enter a word: apple
Please enter a word: grape
Please enter a word: cherry
Please enter a word: grape
Please enter a word: banana
Please enter a word: stop
Produces this file:
grape
banana
cherry
apple
I'm trying to take a text file, and when the user presses any key 25 lines of a text file are printed, then when the key is pressed again, then next 25 lines are printed etc.
So far I've got this code:
f = open("lab6text.txt", "r");
print f
for line in f.readlines():
print line,
But no matter what number I put in the:
f.readlines(25):
Every line is still printed. How can I fix this?
Thanks!
The easier way to read files in "chunks" is to use the iter(callable, sentinel) function.
def make_lines_reader(fobj, number_of_lines):
def reader():
return ''.join(fobj.readline() for _ in range(number_of_lines))
return reader
with open('the-file.txt') as f:
for chunk in iter(make_lines_reader(f, 25), ''):
print(chunk, end='')
input() #assuming python3, in python2 use raw_input()
This will print 25 lines from the-file.txt then wait for the user to press enter. Afterwards it will print other 25 lines etc.
readlines does not take the number of lines as an argument. It instead takes a hint, which is the maximum number of bytes/characters to read in. Unless you know the length of each line, this probably won't serve your purposes well.
If you want to print the next 25 lines of a file, you could use a list comprehension, readline, and join:
print "".join([ f.readline() for _ in range(25) ])
In this manner, you wouldn't have to load all the file at once, but just the next 25 lines.
You could nest this (or something similar) inside a while loop to load more lines from the file when the user presses a key.
You could declare a function that prints a maximum of 25 lines and return whether the end of the file were encountered.
def print25lines(f):
for _ in range(25):
line = f.readline()
if line:
print line,
else:
return False
return True
with open('lab6text.txt', 'r') as f:
while print25lines(f):
# Wait user to press enter
raw_input("Press Enter to continue...")