Saving user output to file with while loop - python

I'm going through some exercises and I can't just figure this out.
Write a while loop that prompts users for their name. When they enter their name, print a greeting to the screen and add a line recording their visit in a file called guest_book.txt. Make sure each entry appears on a new line in the file.
Honestly, I spent way to much time on that and it seems like I'm not understanding the logic of working with files. I think the f.write should be directly under with open in order for the user input to be saved in the file but that's as much as I know. Can you please help me?
My attempts:
filename = 'guest_book.txt'
with open(filename, 'w') as f:
lines = input('Input your name to save in the file: ')
while True:
for line in lines:
f.write(input('Input your name to save in the file'))
I had some more hopes for the second one but still doesn't work.
filename = 'guest_book.txt'
prompt = "Input your name to be saved in guest book: "
active = True
with open(filename, 'w') as f:
while active:
message = f.write(input(prompt))
if message == 'quit':
break
else:
print(message)

A bit of rejigging will get the code as you've written it to work. The main issue is that you can't use the output of f.write() as the value of message, as it doesn't contain the message, it contains the number of characters written to the file, so it will never contain quit. Also, you want to do the write after you have checked for quit otherwise you will write quit to the file.
filename = 'guest_book.txt'
prompt = "Input your name to be saved in guest book: "
active = True
with open(filename, 'w') as f:
while active:
message = input(prompt)
if message == 'quit':
active = False
else:
f.write(message + '\n')
print(message)
Note: I have changed the break to active = False as you have written it as while active:, but you would have been fine with just while True: and break

filename = 'guest_book.txt'
prompt = "Input your name to be saved in guest book: "
active = True
with open(filename, 'w') as f:
while active:
message = input(prompt)
if message == 'quit':
break
else:
print(message)
f.write(message + '\n')
This might work. Assigning message = f.write(...) will make its value the return value of f.write().

Try this..
filename = 'guest_book.txt'
name = ''
with open(filename, 'w') as f:
while name != 'quit':
name = input('Input your name to save in the file: ')
if(name == 'quit'):
break
f.write(name + '\n')

You can use open(filename, 'a') when a stands for append that way you can append a new line to the file each loop iteration.
see: How do you append to a file in Python?
To learn about file handling see: https://www.w3schools.com/python/python_file_handling.asp
Good luck!

For anyone wondering how to solve the whole thing. We're using append instead of write in order to keep all the guests that have been using the programme in the past. Write would override the file.
filename = 'guest_book.txt'
print("Enter 'quit' when you are finished.")
while True:
name = input("\nWhat's your name? ")
if name == 'quit':
break
else:
with open(filename, 'a') as f:
f.write(name + "\n")
print(f"Hi {name}, you've been added to the guest book.")

Related

How to prompt user that asks a user for a file name?

I am going through Intro to Programming so basic stuff here, I have an assignment to "write a program that asks a user for a file name and then displays the first 5 lines of the file," I just can't figure out how to use the input command in this situation and then transfer to open()
Edit: Sorry here is a code snippet I had, I just don't get how to apply input from here.
def main():
#This function writes to the testFile.docx file
outfile = open('testFile.docx', 'w')
outfile.write('Hello World\n')
outfile.write('It is raining outside\n')
outfile.write('Ashley is sick\n')
outfile.write('My dogs name is Bailey\n')
outfile.write('My cats name is Remi\n')
outfile.write('Spam Eggs and Spam\n')
outfile.close()
infile = open('testFile.docx', 'r')
testFileContent = infile.read()
infile.close()
print(testFileContent)
main()
First, we ask for a filename. Then we use the try clause, which checks whether the file exists. If it does it will print 5 lines. If it does not, it will print No such a file found!
x = input('Enter a file name')
try:
with open(x) as f:
data = f.readlines()
for i in range(5):
print(data[i])
except:
print('No such a file found!')
Using a simple function,
def hello_user():
user_input = input('Enter file name: ')
try:
with open(user_input, 'r') as f:
data = f.readlines()
data = data[:5]
for o in data:
print(o.strip())
except FileNotFoundError:
print('Not found ')
hello_user()
It asks for a file name
If the file exists in the same directory the script is running, it opens the file and read each lines (white lines inclusive)
We select only the first 5 lines
We iterate through the list and remove the extra whitespace character(e.g \n).
If the file was not found, we catch the exception.
input() is used to receive input from the user. Once we recieve the input, we use the open() method to read the file in read mode.
def main():
file = input("Please enter a file name")
with open(file, 'r') as f:
lines = f.readlines()
print(lines[:5])
The with statement makes sure that it closes the file automatically without explicitly calling f.close()
The method f.readlines() returns an array containing the lines in the file.
The print() statement prints the first 5 lines of the file.

I am prompted with an error message when I run it

I have this program working how it should be but there is 1 small problem that I'm having and I really don't know what to do about it. I feel like to fix the problem I have to reformat my entire program. In the very beginning of the while loop. I created a with statement that executes what the program is supposed to do. The program opens a file, reads it, and outputs how many unique words there are in a text file. The with statement works, but now the error checking past the with statement does not execute and I'm prompted with an error. When you input a file that does not exist it is supposed to prompt the user saying "The file (filename) does not exist!" But that code past the with statement is no longer executed and I'm prompted with a FileNotFoundError.
def FileCheck(fn):
try:
open(fn, "r")
return 1
except IOError:
print("The file " + filename + " was not found!")
return 0
loop = 'y'
while loop == 'y':
filename = input("Enter the name of the file you wish to process?: ")
with open(filename, "r") as file:
lines = file.read().splitlines()
uniques = set()
for line in lines:
uniques = set(line.split())
print("There are " + str(len(uniques)) + " unique words in " + filename + ".")
if FileCheck(filename) == 1:
loop = 'n'
else:
exit_or_continue = input("Enter the name of the file you wish to process or type exit to quit: ")
if exit_or_continue == 'exit':
print("Thanks for using the program!")
loop = 'n'
else:
break
Here is the error message when I input a file that does not exist
Enter the name of the file you wish to process?: aonsd.txt
Traceback (most recent call last):
File "C:/Users/C/PycharmProjects", line 21, in <module>
with open(filename, "r") as file:
FileNotFoundError: [Errno 2] No such file or directory: 'aonsd.txt'
Your problem is a logic problem here:
filename = input("Enter the name of the file you wish to process?: ")
with open(filename, "r") as file:
...
if FileCheck(filename) == 1:
You very clearly input a file name and then, without bothering to check its existence, try to open it. You don't check until you've finished reading the file.
The logic you expressed in your written description suggests that you want
filename = input("Enter the name of the file you wish to process?: ")
if FileCheck(filename):
with open(filename, "r") as file:
...

Error whilst trying to delete string from a 'txt' file - Contacts list program

I'm creating a Contact list/book program which can create new contacts for you. Save them in a 'txt' file. List all contacts, and delete existing contacts. Well sort of. In my delete function there is an error which happens and I can't quite tell why?. There isn't a error prompted on the shell when running. It's meant to ask the user which contact they want to delete, find what the user said in the 'txt' file. Then delete it. It can find it easily, however it just doesn't delete the string at all.
I have tried other methods including if/else statements, other online code (copied) - nothing works.
import os, time, random, sys, pyautogui
#function for creating a new contact.
def new_contact():
name = str(input("Clients name?\n:"))
name = name + " -"
info = str(input("Info about the client?\n:"))
#starts formatting clients name and info for injection into file.
total = "\n\n"
total = total + name
total = total + " "
total = total + info
total = total + "\n"
#Injects info into file.
with open("DATA.txt", "a") as file:
file.write(str(total))
file.close
main()
#function for listing ALL contacts made.
def list():
file = open("DATA.txt", "r")
read = file.read()
file.close
#detects whether there are any contacts at all. If there are none the only str in the file is "Clients:"
if read == "Clients:":
op = str(input("You havn't made any contacts yet..\nDo you wish to make one?\n:"))
if op == "y":
new_contact()
else:
main()
else:
print (read)
os.system('pause')
main()
#Function for deleting contact
def delete_contact():
file = open("DATA.txt", "r")
read = file.read()
file.close
#detects whether there are any contacts at all. If there are none the only str in the file is "Clients:"
if read == "Clients:":
op = str(input("You havn't made any contacts yet..\nDo you wish to make one?\n:"))
if op == "y":
new_contact()
else:
main()
else:
#tries to delete whatever was inputted by the user.
file = open("DATA.txt", "r")
read = file.read()
file.close
print (read, "\n")
op = input("copy the Clinets name and information you wish to delete\n:")
with open("DATA.txt") as f:
reptext=f.read().replace((op), '')
with open("FileName", "w") as f:
f.write(reptext)
main()
#Main Menu Basically.
def main():
list_contacts = str(input("List contacts? - L\n\n\nDo you want to make a new contact - N\n\n\nDo you want to delete a contact? - D\n:"))
if list_contacts in ("L", "l"):
list()
elif list_contacts in ("N", "n"):
new_contact()
elif list_contacts in ("D", "d"):
delete_contact()
else:
main()
main()
It is expected to delete everything the user inputs from the txt file. No errors show up on shell/console, it's as if the program thinks it's done it, but it hasn't. The content in the txt file contains:
Clients:
Erich - Developer
Bob - Test subject
In your delete function, instead of opening DATA.txt, you open "FileName"
When using “with”, a file handle doesn't need to be closed. Also, file.close() is a function, you didnt call the function, just its address.
In addition, in the delete function, you opened “fileName” instead of “DATA.txt”

Writing functions to allow user define file name and enter file contents

I am learning Python as a beginner and have a question that I couldn't figure out. I need to write functions to allow users to setup/give a file a name and then enter contents.
The error message I got is: "Str' object is not callable. I don't know how to fix this. Please could you help me out. Many thanks!
The code is as follows:
=========================================
WRITE = "w"
APPEND = "a"
fName = ""
def fileName(): #to define name of the file.
fName = input("Please enter a name for your file: ")
fileName = open(fName, WRITE)
return fileName
#now to define a function for data entry
dataEntry = ""
def enterData():
dataEntry = input("Please enter guest name and age, separated by a coma: ")
dataFile = open(fName, APPEND(dataEntry))
fName.append(dataEntry)
return dataFile
#to determine if it's the end of data entry
moreEntry = input("Anymore guest: Y/N ")
while moreEntry != "N":
enterData() #here to call function to repeat data entry
fName.close()
fileName()
enterData()
print("Your file has been completed!")
fileContents = fName.readline()
print(fileContents)
I ran the code and... I seeing the error as line 14
14 dataFile = open(fName, APPEND(dataEntry))
APPEND appears to be a str. It does not appear to be a function.
fName is not declared in this scope. Your function spacing is off. Maybe you meant to run the all the code in order rather than in parts?
As it is, fName is declared and defined once globally (line 4), declared and defined in function filename() (line 6).
fName is also referred to in the function (line 7) Called unsuccessfully in line 14
dataFile = open(fName, APPEND(dataEntry)) # fName has not been declared in function enterData()
I suspect your code would work if you reordered your lines and not use functions (due to references) Also, please close your files. EG
f = open ("somefile.txt", "a+")
...
f.close() #all in the same block.
Thanks for all the inputs. Much appreciated. I've reworked the code a bit, and to put all data entry into a list first, then try to append the list to the file. It works, to a certain extent (about 80%, perhaps!)
However, I now have another problem. When I tried to open the file to append the list, it says "No such file or directory" next to the code (line31): "myFile = open(fName, APPEND)". But I thought I declared and then let user define the name at the beginning? How should I make it work, please?
Thanks in advance again!
WRITE = "w"
APPEND = "a"
fName = ""
def fileName(): #to define name of the file.
fName = input("Please enter a name for your file: ")
fileName = open(fName, WRITE)
fileName.close()
return fileName
#now to define a function for data entry
dataEntry = ""
dataList = []
def enterData():
dataEntry = input("Please enter guest name and age, separated by a coma: ")
dataList.append(dataEntry)
return
fileName()
enterData()
#to determine if it's the end of data entry
moreEntry = input("Anymore guest: Y/N ")
if moreEntry == "Y":
enterData()
else:
print("Your file has been completed successfully!")
myFile = open(fName, APPEND)
myFile.append(dataList)
myFile.close()
fileContents = fName.readline()
print(fileContents)

How do I remove a particular line from a file but keep other lines intact?

I want to learn Python so I started writing my first program which is a phone book directory.
It has the options to add a name and phone number, remove numbers, and search for them.
Ive been stuck on the remove part for about 2 days now and just can't get it working correctly. I've been in the Python IRC and everything, but haven't been able to figure it out.
Basically, my program stores the numbers to a list in a file. I cannot figure out how to remove a particular line in the file but keep the rest of the file intact. Can someone please help me with this?
Some people have advised that it will be easier to do if I create a temp file, remove the line, then copy the remaining lines from the original file over to the temp file. Then write over the original file over with the temp file. So I have been trying this...
if ui == 'remove':
coname = raw_input('What company do you want to remove? ') # company name
f = open('codilist.txt', 'r') # original phone number listing
f1 = open('codilist.tmp', 'a') # open a tmp file
for line in f:
if line.strip() != coname.strip():
for line in f:
f1.write(line)
break # WILL LATER OVERWRITE THE codilist.txt WITH THE TMP FILE
else:
f1.write(line)
else:
print 'Error: That company is not listed.'
f1.close()
f.close()
continue
I assume your file contains something like <name><whitespace><number> on each line? If that's the case, you could use something like this for your if statement (error handling not included!):
name, num = line.strip().split()
if name != coname.strip():
# write to file
Suggestion:
Unless there is some specific reason for you to use a custom format, the file format json is quite good for this kind of task. Also note the use of the 'with' statement in these examples, which saves you having to explicitly close the file.
To write the information:
import json
# Somehow build a dict of {coname: num,...}
info = {'companyA': '0123456789', 'companyB': '0987654321'}
with open('codilist.txt', 'w') as f:
json.dump(info, f, indent=4) # Using indent for prettier files
To read/amend the file:
import json
with open('codilist.txt', 'r+') as f:
info = json.load(f)
# Remove coname
if coname in info:
info.pop(coname)
else:
print 'No record exists for ' + coname
# Add 'companyC'
info['companyC'] = '0112233445'
# Write back to file
json.dump(info, f, indent=4)
You'll need python2.6 or later for these examples. If you're on 2.5, you'll need these imports:
import simplejson as json
from __future__ import with_statement
Hope that helps!
Here is a pretty extensively rewritten version:
all the phone data is wrapped into a Phonebook class; data is kept in memory (instead of being saved and reloaded for every call)
it uses the csv module to load and save data
individual actions are turned into short functions or methods (instead of One Big Block of Code)
commands are abstracted into a function-dispatch dictionary (instead of a cascade of if/then tests)
This should be much easier to understand and maintain.
import csv
def show_help():
print('\n'.join([
"Commands:",
" help shows this screen",
" load [file] loads the phonebook (file name is optional)",
" save [file] saves the phonebook (file name is optional)",
" add {name} {number} adds an entry to the phonebook",
" remove {name} removes an entry from the phonebook",
" search {name} displays matching entries",
" list show all entries",
" quit exits the program"
]))
def getparam(val, prompt):
if val is None:
return raw_input(prompt).strip()
else:
return val
class Phonebook(object):
def __init__(self, fname):
self.fname = fname
self.data = []
self.load()
def load(self, fname=None):
if fname is None:
fname = self.fname
try:
with open(fname, 'rb') as inf:
self.data = list(csv.reader(inf))
print("Phonebook loaded")
except IOError:
print("Couldn't open '{}'".format(fname))
def save(self, fname=None):
if fname is None:
fname = self.fname
with open(fname, 'wb') as outf:
csv.writer(outf).writerows(self.data)
print("Phonebook saved")
def add(self, name=None, number=None):
name = getparam(name, 'Company name? ')
number = getparam(number, 'Company number? ')
self.data.append([name,number])
print("Company added")
def remove(self, name=None):
name = getparam(name, 'Company name? ')
before = len(self.data)
self.data = [d for d in self.data if d[0] != name]
after = len(self.data)
print("Deleted {} entries".format(before-after))
def search(self, name=None):
name = getparam(name, 'Company name? ')
found = 0
for c,n in self.data:
if c.startswith(name):
found += 1
print("{:<20} {:<15}".format(c,n))
print("Found {} entries".format(found))
def list(self):
for c,n in self.data:
print("{:<20} {:<15}".format(c,n))
print("Listed {} entries".format(len(self.data)))
def main():
pb = Phonebook('phonebook.csv')
commands = {
'help': show_help,
'load': pb.load,
'save': pb.save,
'add': pb.add,
'remove': pb.remove,
'search': pb.search,
'list': pb.list
}
goodbyes = set(['quit','bye','exit'])
while True:
# get user input
inp = raw_input("#> ").split()
# if something was typed in
if inp:
# first word entered is the command; anything after that is a parameter
cmd,args = inp[0],inp[1:]
if cmd in goodbyes:
# exit the program (can't be delegated to a function)
print 'Goodbye.'
break
elif cmd in commands:
# "I know how to do this..."
try:
# call the appropriate function, and pass any parameters
commands[cmd](*args)
except TypeError:
print("Wrong number of arguments (type 'help' for commands)")
else:
print("I didn't understand that (type 'help' for commands)")
if __name__=="__main__":
main()
Something simple like this will read all of f, and write out all the lines that don't match:
for line in f:
if line.strip() != coname.strip():
f1.write(line)
Ned's answer looks like it should work. If you haven't tried this already, you can set python's interactive debugger above the line in question. Then you can print out the values of line.strip() and coname.strip() to verify you are comparing apples to apples.
for line in f:
import pdb
pdb.set_trace()
if line.strip() != coname.strip():
f1.write(line)
Here's a list of pdb commands.
You probably don't want to open the temp file in append ('a') mode:
f1 = open('codilist.tmp', 'a') # open a tmp file
also, be aware that
for line in f:
...
f1.write(line)
will write everything to the file without newlines.
The basic structure you want is:
for line in myfile:
if not <line-matches-company>:
tmpfile.write(line + '\n') # or print >>tmpfile, line
you'll have to implement <line-matches-company> (there isn't enough information in the question to know what it should be -- perhaps if you showed a couple of lines from your data file..?)
I got this working...
if ui == 'remove':
coname = raw_input('What company do you want to remove? ') # company name
f = open('codilist.txt')
tmpfile = open('codilist.tmp', 'w')
for line in f:
if coname in line:
print coname + ' has been removed.'
else:
tmpfile.write(line)
f.close()
tmpfile.close()
os.rename('codilist.tmp', 'codilist.txt')
continue

Categories