Can't get user input to append to a file - python

So I'm trying to use the command file.write(newItem + "\n") to append text to a file but I'm having a problem. So here is my code:
file=open("devices.txt","a")
while True:
newItem = input('Enter device name:')
if newItem == 'exit':
break
print("All done!")
file.write(newItem + "\n")
The problem here is, since the file.write command is after the exit command, the only thing it's appending to the file is the word exit, which isn't what I want on there at all. I have tried putting it above the if statement but that completely messes it up so I'm not really sure what to do. I've tried looking it up but can't find anything similar to this specific situation.

You'll need to close your file object and put the write inside while block
file=open("devices.txt","a")
while True:
newItem = input('Enter device name:')
if newItem == 'exit':
break
file.write(newItem + "\n")
file.close()
print("All done!")
Alternatively, you can use context manager without the need to call close()
with open("devices.txt","a") as file
while True:
newItem = input('Enter device name:')
if newItem == 'exit':
break
file.write(newItem + "\n")
print("All done!")

Related

I am getting Name Error in else statement

So! I made a simple program that gets a file name as input and open it and read it.
and there is a special file name "mbox.txt", to open it user must insert the pin code, after that user can access the content of the file.
for this I made a if else condition, if fname=="mbox.txt":
insert pass
else:
open it normally,
and yes! I use try,except and finally, if the file does not find execute runs the except code otherwise continue with finally.
when ever I insert unknown file name it runs the except code and gives the NameError.
fname=input("Enter the file name: ")
try:
open_file=open(fname)
except:
print("The File'",fname,"'Did not find Please Enter A Existing File")
finally:
y=3
if fname=="mbox.txt":
while y>0:
print("To Open This File You Need To Insert The Access Passward")
line=int(input("Insert passward"))
if line==8523:
read= open_file.read()
print(read)
break
else:
if y==3 :
print("Access Denied!")
y=y-1
continue
elif y==2:
print("Access Denied!")
y=y-1
continue
else:
print("UNKNOWN USER DETECTED, THE PROGRAM TERMINATE IMMIDIATELY")
break
else:
read= open_file.read()
print(read)
error
Traceback (most recent call last):
File "c:\Users\TRED WINGS\Desktop\py\tempCodeRunnerFile.py", line 30, in <module>
read= open_file.read()
NameError: name 'open_file' is not defined
Here are some control flow suggestions. I am making some guesses:
#!/usr/bin/env python
MAX_ATTEMPTS = 3
attempts = 0
while True:
fname = input("Enter the file name: ")
try:
open_file = open(fname)
break
except FileNotFoundError:
print(f"{fname} could not be found, please enter a file that exists.")
if fname == "mbox.txt":
print("To Open This File You Need To Insert The Access Password")
while MAX_ATTEMPTS > 0:
line = input("Insert password (numbers only): ")
if not line.isdigit():
print("Invalid password, must pass digits, e.g. 2388")
# Uncomment next line to count invalid entries against attempts:
# attempts += 1
continue
if int(line) == 8523:
read = open_file.read()
print(read)
break
if attempts >= MAX_ATTEMPTS:
print("UNKNOWN USER DETECTED, THE PROGRAM TERMINATE IMMIDIATELY")
break
else:
attempts += 1
print("Access Denied!")
else:
read = open_file.read()
print(read)
File entry:
Wrap the file entry in a while True loop to continue until it finds an existing file.
Use try / catch pattern wrapping open(file, mode='r') and catching FileNotFoundError
Attempts:
Use constant (all upper case) for max attempts
Set attempts to 0
Optionally added a type check to make sure numbers/digits are entered
Uncomment attempts += 1 if you want invalid entries to count toward retries
In the if condition, check for exhausting the max number of retries first
Remove continue unless its needed to skip the rest of the loops (if it's the last line in the loop's block, it a noop)

I need with perfecting a project for beginners in terms of writing to a file

I'm trying to make sure the input the user uses is all letters.I tried the .alpha method but since this is a file, a "." will be included returning it false. I also tried using "quit" sentinel value to exit the program but that isn't working. It keeps saying break is outside the loop. I also want the user to keep inputting if the file is not found error is raised.
The Assignment1
def main():
fileName = inputTxt()
FiletoReadFrom = openingFile(fileName)
counter = 0
for line in FiletoReadFrom:
outputFile = open("output.txt", "a+")
counter = counter + 1
outputFile.write("/* {} */ {}\n".format(counter, line.strip()))
if counter == 0:
print("This is an empty file")
else:
print("The file has been made")
FiletoReadFrom.close()
outputFile.close()
def inputTxt():
flag = True
while flag == True:
FileName= input("Please Enter the Name of the File, or type quit to exit ")
if FileName == quit:
flag == False
break
print("goodbye")
else:
return FileName
def openingFile(filetoReadFrom):
try:
a = open(filetoReadFrom, 'r')
return a
except FileNotFoundError:
print("This File was not Found", "Enter again or type quit to exit")
main()
There are different questions here, which is frowned upon on this site. Please never do that again.
the quit and break problem:
It is just a typo. As you forgot quoting 'quit', Python sees it at an undeclared variable which gives a syntax error. Fix:
...
while flag == True:
FileName= input("Please Enter the Name of the File, or type quit to exit ")
if FileName == 'quit':
flag == False
break
...
But it is still wrong, because break will only exit from the loop and inputTxt will return None which is not what you expect. Calling sys.exit() could be better here.
Test for letters and not numbers:
You must choose a white list (only alphas and dot) or black list (no numbers) way. In idiomatic Python it could be:
if all((x.isalpha() or x == '.') for x in FileName): # white list
# process error condition
if any(x.isdigit() for x in FileName): # black list
# process error condition
You could also use the re module which is great at controlling that a string respect a given pattern...
keep asking until a valid file is given:
You should use a loop:
def main():
while True:
fileName = inputTxt()
FiletoReadFrom = openingFile(fileName)
if FileToReadFrom is not None: # openingFile returns None when file does not exist
break
But IMHO, you should remove the openingFile function and directly use (and test) open in main

Looping a Try/Except block until a file can be read

I have a try/except block in a function that asks the user to enter the name of a text file to open. If the file does not exist, I want the program to ask the user for the filename again either until it is located or the user hits ENTER.
Right now the try/except block just runs infinitely.
def getFiles(cryptSelection):
# Function Variable Definitions
inputFile = input("\nEnter the file to " + cryptSelection +\
". Press Enter alone to abort: ")
while True:
if inputFile != '':
try:
fileText = open(inputFile, "r")
fileText.close()
except IOError:
print("Error - that file does not exist. Try again.")
elif inputFile == '':
input("\nRun complete. Press the Enter key to exit.")
else:
print("\nError - Invalid option. Please select again.")
return inputFile
You need to break out of the while loop, this has to be done at 2 places:
After reading the file (when it is a correct file)
After the Enter key is pressed. because we want to end.
Also you need to prompt the question inside the loop so the question is asked again at every iteration and the inputFile value is updated with the latest user input
One last thing, I think your else clause can be removed as it is never accessed, the if and elif catch all the possibilities (ie, inputFile has a value or not).
def getFiles(cryptSelection):
while True:
inputFile = input("\nEnter the file to %s. Press Enter alone to abort:" % cryptSelection)
if inputFile != '':
try:
fileText = open(inputFile, "r")
fileText.close()
# break out of the loop as we have a correct file
break
except IOError:
print("Error - that file does not exist. Try again.")
else: # This is the Enter key pressed event
break
return inputFile
you have a while True but no break in your code you probably want to break after the fileText.close() like this:
try:
fileText = open(inputFile, "r")
fileText.close()
break
except IOError:
print("Error - that file does not exist. Try again.")
but really you should change this check to use os.path.isfile like this:
import os
def getFiles(cryptSelection):
inputFile = input("\nEnter the file to " + cryptSelection +\
". Press Enter alone to abort: ")
while True:
if inputFile != '':
if os.path.isfile(inputFile):
return inputFile
else:
print("Error - that file does not exist. Try again.")
elif inputFile == '':
input("\nRun complete. Press the Enter key to exit.")
else:
print("\nError - Invalid option. Please select again.")
That is because you don't assign a new value to inputFile within the while loop.
It will hold the same value forever...
EDIT
Once you will assign a new value to inputFile within the loop - make sure to break out when the exit condition is met ("user hits Enter")

UnpicklingError: pickle data was truncated when trying to read a dictionary from a shelved file

I'm a teacher, and I'm trying to write a simple function that saves my students' emails in a dictionary for use in another program. I need the dictionary to be saved across multiple executions, so I'm trying to use shelve to save it; however, after running the function for a second time, I get an unpickling error saying the pickle data was truncated. Here is the code:
shelfFile = shelve.open('mydata')
studentEmails = shelfFile['studentEmails']
def inputEmails():
while True:
nameInput = input('Name: ')
if nameInput == '':
break
emailInput = input('Email: ')
if emailInput == '':
print('Email not entered. Please try again.')
continue
while True:
print('Is this information correct? [Y]es or [N]o')
print('Name: ' + nameInput)
print('Email: ' + emailInput)
correctChoice = input('[Y] or [N]: ').upper()
if correctChoice == 'Y':
studentEmails[nameInput] = emailInput
break
elif correctChoice == 'N':
print('Okay. Please input again.')
break
else:
print('I did not understand that response.')
inputEmails()
shelfFile['studentEmails']=studentEmails
shelfFile.close()
I create the empty dictionary shelfFile['studentEmails'] in the shell before I run the program. It will run fine the first time, but give me the _pickle.UnpicklingError: pickle data was truncated error when I try to assign the shelfFile back to studentEmails. I'm new at this and still learning, so I appreciate the help.
I just had the same problem, and after a little investigation I realized it probably happened because I stopped my program like a jerk (terminated it in the middle of using the shelve).
So I deleted my shelve and created it again and everything worked fine.
I assume you had the same error, maybe you exited your infinite while loops by terminating the program or something?
After toying around with things and reading a few other websites, I was able to achieve what I wanted using pickle instead of shelve. Here is what the code looks like now:
import pickle
loadData = open('saveData.p','rb')
studentEmails = pickle.load(loadData)
loadData.close()
def inputEmails():
while True:
nameInput = input('Name: ')
if nameInput == '':
break
emailInput = input('Email: ')
if emailInput == '':
print('Email not entered. Please try again.')
continue
while True:
print('Is this information correct? [Y]es or [N]o')
print('Name: ' + nameInput)
print('Email: ' + emailInput)
correctChoice = input('[Y] or [N]: ').upper()
if correctChoice == 'Y':
studentEmails[nameInput] = emailInput
break
elif correctChoice == 'N':
print('Okay. Please input again.')
break
else:
print('I did not understand that response.')
inputEmails()
saveData = open('saveData.p','wb')
pickle.dump(studentEmails,saveData)
saveData.close()
This works just fine for what I'm doing. I had to create the studentEmails dictionary in the shell with placeholders as pickle doesn't allow for empty dictionaries.

File saving issue PYTHON - duplicate files?

I am developing a program, and one of the options is to save the data. Although there is a thread similar to this, it was never fully resolved ( Creating file loop ). The problem is, the program does not recognise duplicate files, and I don't know how to loop it so that if there is a duplicate file name and the user does not want to overwrite the existing one, the program will ask for a new name. This is my current code:
print("Exporting")
import os
my_file = input("Enter a file name")
while os.path.isfile(my_file) == True:
while input("File already exists. Overwrite it? (y/n) ") == 'n':
my_file = open("filename.txt", 'w+')
# writing to the file part
my_file = open("filename.txt", 'w+')
# otherwise writing to the file part
file_selected = False
file_path = ""
while not file_selected:
file_path = input("Enter a file name")
if os.path.isfile(file_path) and input("Are you sure you want to override the file? (y/n)") != 'y':
continue
file_selected = True
#Now you can open the file using open()
This holds a boolean variable file_selected.
First, it asks the user for a file name. If this file exists and the user doesn't want to override it it continues (stops the current iteration and continues to the next one), so the user is asked again to enter a file name. (pay attention that the confirmation will execute only if the file exists because of lazy evaluation)
Then, if the file doesn't exist or the user decided to override it, file_selected is changed to True, and the loop is stopped.
Now, you can use the variable file_path to open the file
Disclaimer: This code is not tested and only should theoretically work.
Although the other answer works I think this code is more explicit about file name usage rules and easier to read:
import os
# prompt for file and continue until a unique name is entered or
# user allows overwrite
while 1:
my_file = input("Enter a file name: ")
if not os.path.exists(my_file):
break
if input("Are you sure you want to override the file? (y/n)") == 'y':
break
# use the file
print("Opening " + my_file)
with open(my_file, "w+") as fp:
fp.write('hello\n')
This is how I advise to do it, especially when you have event driven GUI app.
import os
def GetEntry (prompt="Enter filename: "):
fn = ""
while fn=="":
try: fn = raw_input(prompt)
except KeyboardInterrupt: return
return fn
def GetYesNo (prompt="Yes, No, Cancel? [Y/N/C]: "):
ync = GetEntry(prompt)
if ync==None: return
ync = ync.strip().lower()
if ync.startswith("y"): return 1
elif ync.startswith("n"): return 0
elif ync.startswith("c"): return
else:
print "Invalid entry!"
return GetYesNo(prompt)
data = "Blah-blah, something to save!!!"
def SaveFile ():
p = GetEntry()
if p==None:
print "Saving canceled!"
return
if os.path.isfile(p):
print "The file '%s' already exists! Do you wish to replace it?" % p
ync = GetYesNo()
if ync==None:
print "Saving canceled!"
return
if ync==0:
print "Choose another filename."
return SaveFile()
else: print "'%s' will be overwritten!" % p
# Save actual data
f = open(p, "wb")
f.write(data)
f.close()

Categories

Resources