there is a part of my program where I would like to pass a sorted list of names from a text file to a function which asks the user to enter a name and then indicate whether the name entered is found in the list or not. If the name is found, its position (i.e. index) is also printed.
The file is just 30 names, but when the second function is executed, it will show this after I input which name I would like to search for:
name not found.
name not found.
name found
name not found.
name not found.
...etc for all 30 names.
Here's the code:
def main():
infile = open('names.txt', 'r')
line = infile.readline()
while line !='':
line = line.rstrip('\n')
print(line)
line = infile.readline()
print('\nHere are the names sorted:\n')
infile = open("names.txt", 'r')
names = infile.readlines()
names.sort()
for line in names:
line = line.rstrip('\n')
print(line)
line = infile.readline()
search_file(line) # I don't this this is the correct way to
# pass the sorted list of names?
def search_file(line):
search = open('names.txt', 'r')
user_search = input('\nSearch for a name(Last, First): ')
#item_index = line.index(search)
print()
with open('names.txt', 'r') as f:
for line in f:
if user_search in line:
print('name found')#, item_index)
else:
print('name not found.')
updated code here:
this time it always displays "not found"
def search_file(line):
user_search = input('\nSearch for a name(Last, First): ')
print()
try:
item_index = line.index(user_search)
print(user_search, 'found at index', item_index)
except ValueError:
print('not found.')
Well first you would only want to open the file you are searching one time. You could load all lines in the file into a list with .readlines() this function returns a string in a list for each line. Then you can search for the user string with in each line with
for l in lines:
if (l.find(userstring)>-1):
foundvar=True
Related
So im making a name generator/finder, So for the find command i want to find that name in the txt file with the line number! So how do i find the name with the line number?
line = 0
names = open(r"names.txt", "r")
name1 = names.readlines()
uname = input("Please enter the name you want to find: ")
for name in name1:
try:
print(name)
print(line)
if name == uname:
print(f"Found name: {name} \nLine No. {line + 1}")
else:
line = line + 1
except:
print("Unable to process")
But it seems to not work except if you write the last name in file it works. So could give any help?
EDIT: Ive found a way so you can reply if you want to for further people running into the problem!
Try this:
with open("names.txt", "r") as f:
file_contents = names.read().splitlines()
uname = input("Please enter the name you want to find: ")
for line, row in enumerate(file_contents):
if uname in row:
print('Name "{0}" found in line {1}'.format(uname, line))
Yo
if "namefilled" in name :
print("found it")
You can use pathlib if you have Python 3.4+. Pretty handy library.
Also, context management is useful.
# Using pathlib
from pathlib import Path
# https://docs.python.org/3/library/fnmatch.html?highlight=fnmatch#module-fnmatch
import fnmatch
# Create Path() instance with path to text file (can be reference)
txt_file = Path(r"names.txt")
# Gather input
uname = input("Please enter the name you want to find: ")
# Set initial line variable
line = 0
find_all = False
# Use context maangement to auto-close file once complete.
with txt_file.open() as f:
for line in f.readlines():
# If python 3.8, you can use assignment operator (:=)
if match_list := fnmatch.filter(line, uname) is not None: # Doe not match substring.
number_of_names = len(match_list)
name_index = [i for i, element in enumerate(line.split()) for word in match_list if word == element]
print(f"""
{number_of_names} name{"s" if number_of_names > 0 else ""} found on line {line} at position {name_index}.
""".strip())
line += 1
Edited to include fnmatch per some other comments in this thread about matching the full string vs. a substring.
You could try something like this:
import re
search_name = input("Enter the name to find: ")
with open("names.txt", "r") as f:
for line, row in enumerate(f.read().splitlines()):
if re.findall('\\b'+search_name+'\\b', row, flags=re.IGNORECASE):
print('Name "{0}" found in line {1}'.format(search_name, line))
You can remove the flags=re.IGNORECASE flag in case you want the seaarch to be case-sensetive.
I am having trouble with matching variables to lines in txt, and removing the lines.
I am currently doing a hotel room booking program in which I am having trouble removing a booking from my text file.
This is how my lines in my text file are formatted:
first_name1, phonenumber1 and email 1 are linked to entry boxes
jeff;jeff#gmail.com;123123123;2019-06-09;2019-06-10;Single Room
def edit_details(self,controller):
f = open("Bookings.txt")
lines = f.readlines()
f.close()
x = -1
for i in lines:
x += 1
data = lines[x]
first_name1 = str(controller.editName.get())
phonenumber1 = str(controller.editPhone.get())
email1 = str(controller.editEmail.get())
checkfirst_name, checkemail, checkphone_num, checkclock_in_date, checkclock_out_date, checkroom = map(str, data.split(";"))
if checkfirst_name.upper() == first_name1.upper() and checkemail.upper() == email1.upper() and checkphone_num == phonenumber1:
controller.roomName.set(checkfirst_name)
controller.roomEmail.set(checkemail)
controller.roomPhone.set(checkphone_num)
controller.roomCheckin.set(checkclock_in_date)
controller.roomCheckout.set(checkclock_out_date)
controller.roomSelect.set(checkroom)
print(controller.roomName.get())
print(controller.roomSelect.get())
controller.show_frame("cancelBooking")
break
elif x > len(lines) - int(2):
messagebox.showerror("Error", "Please Enter Valid Details")
break
I have the user to enter their details to give me the variables but I don't know how to match these variables to the line in the text file to remove the booking.
Do I have to format these variables to match the line?
This is what i have tried but it deletes the last line in my file
line_to_match = ';'.join([controller.roomName.get(),controller.roomEmail.get(),controller.roomPhone.get()])
print(line_to_match)
with open("Bookings.txt", "r+") as f:
line = f.readlines()
f.seek(0)
for i in line:
if i.startswith(line_to_match):
f.write(i)
f.truncate()
I have kind of added a pseudocode here. You can join the variables using ; and validate if the line startswith those details, like below.
first_name1, phonenumber1, email1 = 'jeff', 'jeff#gmail.com', '123123123'
line_to_match = ';'.join([first_name1, email1, phonenumber1])
for i in line:
...
if i.startswith(line_to_match):
# Add your removal code here
...
I am stuck why the words.txt is not showing the full grid, below is the tasks i must carry out:
write code to prompt the user for a filename, and attempt to open the file whose name is supplied. If the file cannot be opened the user should be asked to supply another filename; this should continue until a file has been successfully opened.
The file will contain on each line a row from the words grid. Write code to read, in turn, each line of the file, remove the newline character and append the resulting string to a list of strings.After the input is complete the grid should be displayed on the screen.
Below is the code i have carried out so far, any help would be appreciated:
file = input("Enter a filename: ")
try:
a = open(file)
with open(file) as a:
x = [line.strip() for line in a]
print (a)
except IOError as e:
print ("File Does Not Exist")
Note: Always avoid using variable names like file, list as they are built in python types
while True:
filename = raw_input(' filename: ')
try:
lines = [line.strip() for line in open(filename)]
print lines
break
except IOError as e:
print 'No file found'
continue
The below implementation should work:
# loop
while(True):
# don't use name 'file', it's a data type
the_file = raw_input("Enter a filename: ")
try:
with open(the_file) as a:
x = [line.strip() for line in a]
# I think you meant to print x, not a
print(x)
break
except IOError as e:
print("File Does Not Exist")
You need a while loop?
while True:
file = input("Enter a filename: ")
try:
a = open(file)
with open(file) as a:
x = [line.strip() for line in a]
print (a)
break
except IOError:
pass
This will keep asking untill a valid file is provided.
I have a file which contains a user:
Sep 15 04:34:31 li146-252 sshd[13326]: Failed password for invalid user ronda from 212.58.111.170 port 42579 ssh2
Trying to use index method for string to edit the user within the file. So far I am able to print the user but now to delete and put in the new user.
newuser = 'PeterB'
with open ('test.txt') as file:
for line in file.readlines():
lines = line.split()
string = ' '.join(lines)
print string.index('user')+1
Do you want to update the file contents? If so, you can update the user name, but you will need to rewrite the file, or write to a second file (for safety):
keyword = 'user'
newuser = 'PeterB'
with open('test.txt') as infile, open('updated.txt', 'w') as outfile:
for line in infile.readlines():
words = line.split()
try:
index = words.index(keyword) + 1
words[index] = newuser
outfile.write('{}\n'.format(' '.join(words)))
except (ValueError, IndexError):
outfile.write(line) # no keyword, or keyword at end of line
Note that this code assumes that each word in the output file is to be separated by a single space.
Also note that this code does not drop lines that do not contain the keyword in them (as do other solutions).
If you want to preserve the original whitespace, regular expressions are very handy, and the resulting code is comparatively simple:
import re
keyword = 'user'
newuser = 'PeterB'
pattern = re.compile(r'({}\s+)(\S+)'.format(keyword))
with open('test.txt') as infile, open('updated.txt', 'w') as outfile:
for line in infile:
outfile.write(pattern.sub(r'\1{}'.format(newuser), line))
If you want to change the names in your log, here is how.
file = open('tmp.txt', 'r')
new_file = []
for line in file.readlines(): # read the lines
line = (line.split(' '))
line[10] = 'vader' # edit the name
new_file.append(' '.join(line)) # store the changes to a variable
file = open('tmp.txt', 'w') # write the new log to file
[file.writelines(line) for line in new_file]
code = raw_input("Enter Code: ')
for line in open('test.txt', 'r'):
if code in line:
print line
else:
print 'Not in file'
The test.txt file looks like this
A 1234567
AB 2345678
ABC 3456789
ABC1 4567890
When input is A
The print line returns all lines with A instead of just the first line. Note: the test.txt file has approximately 2000 entry's. I just want to return the line with the numbers for what ever the user inputs for now
As #Wooble points out in the comments, the problem is your use of the in operator to test for equivalency rather than membership.
code = raw_input("Enter Code: ")
for line in open('test.txt', 'r'):
if code.upper() == line.split()[0].strip().upper():
print line
else:
print 'Not in file'
# this will print after every line, is that what you want?
That said, probably a better idea (dependent on your use case anyway) is to pull the file into a dictionary and use that instead.
def load(filename):
fileinfo = {}
with open(filename) as in_file:
for line in in_file:
key,value = map(str.strip, line.split())
if key in fileinfo:
# how do you want to handle duplicate keys?
else:
fileinfo[key] = value
return fileinfo
Then after you load it all in:
def pick(from_dict):
choice = raw_input("Pick a key: ")
return from_dict.get(choice, "Not in file")
And run as:
>>> data = load("test.txt")
>>> print(pick(data))
Pick a key: A
1234567