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()
Related
I am trying to code this function so that it gets called twice. On the first time it is called, s should be a string 'JSON/image', and the second time it is called, s should be a different string 'second'. The goal is that so when the function is called the first time it will ask:
"Enter JSON/image file"
and the second time it should prompt
"Enter text/txt file"
def open_file(times):
times_run = 0
while times_run <1:
file_name = input("Enter {} file: ".format(times))
try:
fp = open(file_name, 'r')
times_run += 1
return(fp)
except:
print("File not found")
I'm not exactly sure you understand the principles of file handling. You said the goal was to initially get a "Enter a JSON file" and a "Enter a txt file" message. However, your try and except handling isn't working correctly. You're printing "File not found. Try again", but there is no again. The code just stops working since there's no loop or recurrence. This is some code I think will be helpful:
s=('JSON', 'txt')
def check_json(s):
file_name = input("Enter a {} file name: ".format(s[0]))
try:
fp = open(file_name, 'r')
except FileNotFoundError:
print("File not found. Try again.")
return check_json(s)
def check_txt(s):
file_name = input("Enter a {} file name: ".format(s[1]))
try:
fp = open(file_name, 'r')
except FileNotFoundError:
print("File not found. Try again.")
return check_txt(s)
check_json(s)
check_txt(s)
You wanted a variable s even though it could've been done without that and without the format() method. It can obviously be done without functions as well.
I hope this clears things up in terms of changing the format of an input in a function
I am almost sure that you shouldn't do that! I guess you have control over calling it so you could just add extra parameter for your function and based on it decide whether is it JSON or TXT. Saying that, if you don't mind do some ugly things, you could use decorator:
def deco(fun):
def f(s):
f.no_calls += 1
fun(s, f.no_calls)
f.no_calls = 0
return f
#deco
def open_file(s, no_calls): # no_calls parameter will be provided by decorator
if no_calls == 1:
print("JSON")
if no_calls == 2:
print("TXT")
# you call it without second parameter
open_file("") # JSON
open_file("") # TXT
I'm trying to print integers from a file where each line has 1 integer, as well as print their sum. Everything seems to work fine, except when I enter the incorrect file name, loop back, and then enter the correct one. The program still outputs the correct information but then the error:
"AttributeError: 'NoneType' object has no attribute 'readline'". Why is this happening?
def main():
listnums = filetolist()
print(f'numbers in file: {listnums}')
print(f' sum of before mentioned numbers is: {sum(listnums)}')
# opens file
def openfile():
try:
file = open(input("what is the file named including the file extension?"), "r")
return file
except IOError:
tryagain = input("File could not be found \n" + "if you would like try again type 1 and press enter, to exit press enter")
if tryagain == "1":
main()
else:
exit()
# converts file to list
def filetolist():
file = openfile()
line = file.readline()
nums = []
linenumber = 1
while line != "":
nums += [verifyint(line, linenumber)]
line = file.readline()
linenumber += 1
file.close()
return nums
# verifies number is an int
def verifyint(num, linenumber):
try:
numint = int(num)
return numint
except ValueError:
print(f'Invalid value on line #{linenumber}')
exit()
main()
When you hit the except block, there is no return statement, so this function returns None after running main() again
Rather than effectively recurse, you should properly raise the errors and use a proper loop
def filetolist(filename):
with open(filename) as f:
return [int(line.rstrip()) for line in f]
def main():
while True:
filename = input("what is the file named including the file extension?")
try:
listnums = filetolist(filename)
print(f'numbers in file: {listnums}')
print(f' sum of before mentioned numbers is: {sum(listnums)}')
except ValueError, IOError:
again = input('Error! Try again? (y/n)')
if again.lower() != 'y':
break
main()
I think (i might be wrong) that the problem is that when you fail to read a file and try again you need to recall openfile and not the whole main.
If you call the whole main you are opening a new file doing all the routine and then returning nothing.
Try that And tell me if it works
def openfile():
try:
file = open(input("what is the file named including the file extension?"), "r")
return file
except IOError:
tryagain = input("File could not be found \n" + "if you would like try again type 1 and press enter, to exit press enter")
if tryagain == "1":
return openfile()
else:
exit()
here a screenshot
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
I'm trying to modify a trivia program found in a book as part of a tutorial; I need to save the name and score of the player using a pickled dictionary. I've already created the dat file using a separate program, to avoid reading from a file that doesn't exist.
This is the code for the trivia program.
#Trivia Challenge
#Trivia game that reads a plain text file
import sys
def open_file(file_name, mode):
"""Open a file"""
try:
the_file = open(file_name, mode)
except IOError as e:
print("Unable to open the file", file_name, "Ending program.\n", e)
input("\n\nPress the enter key to exit.")
sys.exit()
else:
return the_file
def next_line(the_file):
"""Return next line from the trivia file, formatted."""
line = the_file.readline()
line = line.replace("/", "\n")
return line
def next_block(the_file):
"""Return the next block of data from the triva file."""
category = next_line(the_file)
question = next_line(the_file)
answers = []
for i in range(4):
answers.append(next_line(the_file))
correct = next_line(the_file)
if correct:
correct = correct[0]
explanation = next_line(the_file)
value = next_line(the_file)
return category, question, answers, correct, explanation, value
def welcome(title):
"""Welcome the player and get his or her name."""
print("\t\tWelcome to Trivia Challenge!\n")
print("\t\t", title, "\n")
def saving(player_name):
import pickle
f = open("trivia_scores.dat", "rb+")
highscores = pickle.load(f)
if player_name in highscores and score > highscores[player_name]:
highscores[player_name] = score
pickle.dump(highscores, f)
elif player_name not in highscores:
highscores[player_name] = score
pickle.dump(highscores, f)
print("The current high scores are as follows:")
print(highscores)
f.close()
def main():
trivia_file = open_file("trivia.txt", "r")
title = next_line(trivia_file)
welcome(title)
score = 0
#Get the first block
category, question, answers, correct, explanation, value = next_block(trivia_file)
while category:
#Ask a question
print(category)
print(question)
for i in range(4):
print("\t", i + 1, "-", answers[i])
#Get answer
answer = input("What is your answer?: ")
#Check answer
if answer == correct:
print("\nRight!", end=" ")
score += int(value)
else:
print("\nWrong!", end=" ")
print(explanation)
print("Score:", score, "\n\n")
#Get the next block
category, question, answers, correct, explanation, value = next_block(trivia_file)
trivia_file.close()
print("That was the last question!")
print("Your final score is", score)
return score
player_name = input("First, enter your name: ")
main()
saving(player_name)
input("\n\nPress the enter key to exit.")
The eponymous error occurs at this point:
def saving(player_name):
import pickle
f = open("trivia_scores.dat", "rb+")
highscores = pickle.load(f)
When the questions end, the program attempts to run the "saving" module, which (In theory) opens the trivia_scores.dat file, loads the highscores dictionary, checks to see if the player's name is in the dictionary, and if their current score is higher than the one in the file, it overwrites it.
But for some reason, when the program attempts to load the highscores dictionary, instead I get this error message.
EOFError: Ran out of input
I have never seen this error before. From some cursory googling, I got the impression that it has something to do with the program trying to read from an empty file. But that made no sense to me, since I specifically created a dat file using a different program to prevent that from happening: trivia_scores.dat is NOT an empty file. I even read from it with Python Shell to make sure.
What does this error mean, and why won't Python load the dat file?
Context: The book I'm reading from is Python for the Absolute Beginner, by Michael Dawson. This program and the challenge I'm trying to complete come from chapter 7. The program was running fine before I added the saving module.
Probably the original trivia_scores.dat file you wrote got corrupt (maybe you didn't call close() on it?). You should try creating a new file and adding a pre-populated dictionary to this file. Then try reading from this new file.
So I'm trying to make a program that reads a file, and stores each word into a list of strings. I can add each line into a list of strings, (see the code below) but how do I add each individual word into a list of strings?
Also, since this is a Mad Libs program, I'll have some phrases that will look like, noun, or body part. How would I store body part into the list as one string, since it is technically two separate words?
Code for reference:
def main():
file_list = []
while True: #while loop that runs until the user puts in a file name...
#or types in quit
#asks the user for a file name, or gives them an option to quit
file_name = raw_input("Enter in the name of the file, or type in quit to quit: ")
if file_name == "quit":
sys.exit(0) #quits the program
else:
try: #attempts to open the file
fin = open(file_name)
break
except: #prints out if file name doesn't exist
print "No, no, file no here."
for eachLine in fin: #strips out the new lines from the file
file_list.append(eachLine.strip())
print file_list
if __name__ == '__main__':
main()
file_list.extend(eachLine.split())