File won't open when being passed from a function - python-3.x

How come it's not opening the file I put into the function? It opens when I plug the file name directly into the main program, but not when I try to pass it through the function. It gives me a FileNotFoundError.
def get_valid_filename(prompt):
'''Use prompt (a string) to ask the user to type the name of a file. If
the file does not exist, keep asking until they give a valid filename.
Return the name of that file.'''
filename = input(prompt)
if os.path.isfile(filename) == False:
print ("That file does not exist.")
filename = input(prompt)
return filename
if __name__ == '__main__':
prompt = 'enter the name of the file with unknown author:'
mystery_filename = get_valid_filename(prompt)
# readlines gives us the file as a list of strings each ending in '\n'
text = open(mystery_filename, 'r').read()
print (text)

get_valid_filename should look like this:
def get_valid_filename(prompt):
while True:
filename = input(prompt):
if os.path.exists(filename):
return filename
print('that file does not exist')

Related

List is empty when appending when using recursion

I have two functions. The first one is used to get a list of paths to text files, and the second one is used to iterate over this list of paths and then check if they include the word password. But because of the Try Except statement in the second function, I had to use recursion to make it continue running unless there's another way if possible to provide below. My problem is that the list returned in the second function is empty why and how to fix it?
def search_txt():
"""Function to search the C:\\ for .txt files -> then add them (including full path to file) to a list."""
list_of_txt = []
for dir_path, sub_dir, files in os.walk("C:\\"):
"""Method 1 -> checks the end of the file name (could be used for specific extensions)"""
for file in files:
if file.endswith(".txt"):
list_of_txt.append(os.path.join(dir_path, file))
return list_of_txt
def search_pass_file(list_of_files: list):
"""Function to iterate over each text file, searching if the word "password" is included -> Returns the text
file's path """
list_of_pass = []
if len(list_of_files) != 0:
for i in range(len(list_of_files)):
file = list_of_files.pop()
try:
with open(file, encoding="utf8") as f:
for line in f.readlines():
if "password" in line:
list_of_pass.append(file)
except UnicodeDecodeError:
return search_pass_file(list_of_files)
except PermissionError:
return search_pass_file(list_of_files)
else:
return list_of_pass
if __name__ == '__main__':
myList = search_txt()
print(search_pass_file(myList))
You're returning list_of_pass only if len(list_of_files) == 0 (it's in the else block). Your return statement should occur after the loop (which should be a while one btw)
You can except several errors in one line by putting them in parenthesis: except (UnicodeDecodeError, PermissionError) of except all exceptions (for instance, you're not handling FileNotFoundError).
I'd reduce your function to:
def search_pass_file(list_of_files: list):
"""Function to iterate over each text file, searching if the word "password" is included -> Returns the text
file's path """
list_of_pass = []
while list_of_files:
file = list_of_files.pop()
try:
with open(file, encoding="utf8") as f:
for line in f.readlines():
if "password" in line:
list_of_pass.append(file)
break
except Exception:
list_of_pass += search_pass_file(list_of_files)
return list_of_pass
Edit: also in your except block, you should append the returned value of the recursive function to list_of_pass otherwise you'll lose the files found after the error occurs.

Continues variable not triggering while loop

Apologies if this is a repost. I am trying to write a while loop with a continue variable and if/else statement. My issue is that my continue variable is being ignored I cannot find the problem thus far. So far I have moved the while continues == 'y' condition into the else block now I am a bit flummoxed on why this var is being overlooked.
code:
def add_to_existing_file(data):
# data[0]-api response
# data[1]-city
# infile-file object returned from openFile()
# file_name- file name string. check filetype & report version.
continues = 'y' # set up continue variable
while continues == 'y':
file_name = input("Enter File Path to file to be appended: ") # get file from user
if file_name is False:
print("Now Creating Excel File..") # create condition for no user response.
return # if empty response exit function
else:
infile = appends.openFile(file_name) # open file to work with. Returns file object.
added_data = appends.journal_report_1_to_df(infile, file_name, data[0], data[1]) # append selected file to existing df
continues = input("Do you want to append another file? Y or N").lower() # check if new file
return added_data # return new df w/appended data
The problem happens on the last line. You're returning at the end of the first iteration, which exits the loop. This can be fixed by moving the return to the outer scope.
def add_to_existing_file(data):
# data[0]-api response
# data[1]-city
# infile-file object returned from openFile()
# file_name- file name string. check filetype & report version.
continues = 'y' # set up continue variable
while continues == 'y':
file_name = input("Enter File Path to file to be appended: ") # get file from user
if file_name is False:
print("Now Creating Excel File..") # create condition for no user response.
return # if empty response exit function
else:
infile = appends.openFile(file_name) # open file to work with. Returns file object.
added_data = appends.journal_report_1_to_df(infile, file_name, data[0], data[1]) # append selected file to existing df
continues = input("Do you want to append another file? Y or N").lower() # check if new file
return added_data # return new df w/appended data
It should work if you get the second return line (return added_data # return new df w/appended data) to have the same indentation as your while line. As a basic outline for a continue loop:
def function
continues = 'y'
while
if :
elif :
else :
print
continue ?
return

a funtion can not return right value

I am defining a function for seeking recursively for a file, BUT it's weird that it can't return the path to the file.
At first, I define a function
import os
def searchFile(target,root):
items = os.listdir(root)
for item in items:
path = os.path.join(root,item)
if os.path.isdir(path):
#print(path)
searchFile(target,path)
elif os.path.isfile(path):
#print(path)
if os.path.basename(path) == target:
print('if have already executed!!! ')
print(path)
print(target)
return path
The function behaves as follows
Case 1:
When I use this function to find file_1 in the current path ".", the function return the full path to the file_1
return_value = searchFile(target='file_1',root='.')
print(return_value) # ./file_1
Case 2:
When I use this function to find file_1 in the directory "./result_new" for instance, the function returns "None"
return_value = searchFile(target = 'file_1',root='.')
print(return_value) # None
I expect this function should return the path to the file.
Try replacing First If Block :
if os.path.isdir(path):
#print(path)
path_file = searchFile(target,path)
if path_file is not None:
return path_file
Note : it's because you are not handling the output of multi-level recursive calls.
Code Link: https://ideone.com/D2LlEr
Note-1: it will return path of the first file found.

ELIF statements skipped in favor of ELSE

I am writing a few statements utilizing regular expressions to match an output to a given extension. My For loop seems to work fine, I get an answer back for each of the files and if I take one out or add one, I get a return.
What appears to happen though is that my first file is picked up, matched successfully, and the correct output given. The loop then grabs the next file, checks against the first statement, then skips the two ELIF's and gives and output based on my ELSE. Can anyone point out why or if I have it wrong, what is actually going on?
def extmatch():
global dircontents
for file in dircontents:
dircontents = re.search(".+\sbreakout.*\.ttx", file)
if dircontents:
print('File is for TIA')
elif dircontents:
dircontents = re.search('\w+\.csv+$', file)
if dircontents:
print('File is for NMFTA')
elif dircontents:
dircontents = re.search('\w+.\.txt+$', file)
if dircontents:
print('File is for NMFTA')
else:
print('File type not recognized.')
['061419license breakout_ibc_v3_0116.ttx', '2019-06-17_7-49-21.jpg', 'SampleCSV.csv', 'script_test.txt'] <--- these are the files in the dir indicated
File is for TIA
File type not recognized. <---Seems to match to ELSE for each file past the first
File type not recognized.
File type not recognized.
You probably want something like this:
def extmatch(dircontents):
for filename in dircontents:
if filename.lower().endswith(".ttx"):
print('File is for TIA')
elif filename.lower().endswith(".csv"):
print('File is for NMFTA')
elif filename.lower().endswith(".txt"):
print('File is for NMFTA')
else:
print('File type not recognized.')
or even like this:
EXT_ASSIGNMENTS = {
'ttx': 'TIA',
'csv': 'NMFTA',
'txt': 'NMFTA',
}
def extmatch(dircontents):
for filename in dircontents:
ext = filename.lower().split('.')[-1]
if ext in EXT_ASSIGNMENTS:
print('File is for ' + EXT_ASSIGNMENTS[ext])
else:
print('File type not recognized.')
Avoid global variables. If you need to pass information to a function, use an argument.

Python: Checking file names in a directory one by one

I am asking for user input of a name, and I want to search in the directory of the file with the code whether a file exists that is called the same thing as the inputted name, if yes, then the program asks for a new name, if not, then it will create a file with that name. I am struggling because the code I have written only checks the first file in the directory and doesn't continue with the rest.
The code that I am having the problem with looks something like this:
import os
Name = input("Please enter name for new file")
if Name in os.listdir():
print("Sorry this name already exists, please choose another one")
break
else:
NewFile = open("Name" + ".txt", "w+")
break
You can use glob:
import glob
existing = glob.glob('*.txt')
name = '{}.txt'.format(input("Please enter name for new file"))
if name in existing:
print("Sorry this name already exists, please choose another one")
else:
newfile = open(name, "w+")

Resources