HiveBrain v1.2.0
Get Started
← Back to all entries
debugpythonMinor

Searching for files in a specified directory

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
directorysearchingfilesforspecified

Problem

I am currently writing a program that allows me to search for files in a user-specified directory. My current code is as follows:

```
if os.path.exists(file_path)!= True:
print('\n Path does not exist. \n')

else:
while True:
aa = '''\nWhich search characteristics would you like to use? \n 1. Search by name: N \n 2. Search by extension: E \n 3. Search by size: S
\n Please enter your choice: '''

answer = input(aa).strip()

if answer not in 'NnEeSs' or answer=='':
print('\n Invalid choice. ')

elif answer in 'Nn':
while True:
try:
name = input ('\nEnter file name: ')
rr = search_by_name(name, file_path)
if not rr:
print('\n File not found \n')
else:
break

except WindowsError:
print('\n Oops! Access denied.\n')
continue

elif answer in 'Ee':
while True:
try:
ending = input ('\nEnter the file extension: ')
rr = search_by_extention(ending, file_path)
if not rr:
print('\n No File(s) found \n')
else:
break

except WindowsError:
print('\n Oops! Access denied. \n')
continue

elif answer in 'Ss':
while True:
try:
size = int(input('\nPlease enter file size: '))
rr = search_by_size(size, file_path)
if not rr:
print('\n No file(s) found \n')
else:
break

except ValueError:
print('\n* Enter an

Solution

To improve readability I would try and break the code down into more functions and redefine your pre-determined text values as globals, such that you can save space in the actual function. Responses can be represented by a dictionary value with boolean/text key value pairs (or exception/text). Also certain UI options can be stored in a dictionary, with links to their associated functions.

# using 3 quotes mean you don't need to specify newlines
dir_tools_menu = '''
Which search characteristics would you like to use?
1. Search by name: N 
2. Search by extension: E 
3. Search by size: S
\tPlease enter your choice: '''
dir_tools_options = {"n":ui_search_by_name, 
                     "e":ui_search_by_extention, 
                     "s":ui_search_by_size}
error_response = {WindowsError:"Oops! Access denied.", 
                  ValueError:"Enter an numeric value."}
# add number of files for true
files_found_response = {False:"No file(s) found", 
                        True:"{} file(s) found"}
# add filename
file_found_response = {False:"File {} not found",
                       True:"File {} found"}
file_exists_response ={ False:"Path does not exist.", 
                         True:"Path Found"}
# add choice for true
valid_ui_response = {False:"Invalid choice.", 
                      True:"You choose {}."}


Now that we have a collection of text values lets make a function to standardize print outputs, such that you don't have to write all those stars everywhere, and you can feel assured that they will produce even length lines.

line_length = 40
# or you can have a funky pattern like "`-._.-'-._...
line_pad = "*"*line_length 

def my_print(text, *params):
    # len(params) must match the count of "{}" in the text so this will not crash
    # Perhaps add a check to assert this case
    message = text.format(*params)
    offset = line_length/2 - len(message)/2
    if offset > 0 and offset + len(message) < line_length:
        print(line_pad[:offset] + message + line_pad[offset+len(message):])
    # in the case that a line is larger than the formatting, you can just print the line.
    # its gonna look gross regardless
    else:
        print(message)


Lets also make a simple yes/no function.

yes = ("yes", "y","1")
no = ("no", "n", "0")
def ask_yes_no(question):
    answer = ''
    while not answer in yes + no:
        answer = input(question).lower()
        if not answer in yes + no:
            my_print(valid_ui_response[False])
        else:
            my_print(valid_ui_response[True], return_to_menu)
            # True - yes, False - no
            return answer in yes


Now your main method boils down to..

quit_question = "Quit Dir Tools? "

def dir_tools(file_path):
    if os.path.exists(file_path):
        my_print(file_exists_response[True] )
    else:
        my_print(file_exists_response[False])
        return
    quit_dir_tools = False
    while not quit_dir_tools:
        answer = input(dir_tools_menu).lower()
        if answer not in dir_tools_options:
            my_print(valid_ui_response[False])
        else:
            my_print(valid_ui_response[True],answer)
            dir_tools_options[answer](file_path)
        quit_dir_tools = ask_yes_no(quit_question)


Now for the actual important functions.. I'll just do one example to show the try catch responses,..

ui_sbn_question = 'Enter file name: '
return_question = "Return to main menu? "

def ui_search_by_name(file_path):
    return_to_menu = False
    while not return_to_menu:
        name = input(ui_sbn_question)
        try:
            sbn_response = search_by_name(name, file_path)
            if not sbn_response:
                my_print(file_found_response[False], name)
            else:
                my_print(file_found_response[True], name)
                # assuming that this isnt a boolean
                my_print(sbn_response)
        except WindowsError:
            my_print(error_response[WindowsError])
        return_to_menu = ask_yes_no(return_question)

Code Snippets

# using 3 quotes mean you don't need to specify newlines
dir_tools_menu = '''
Which search characteristics would you like to use?
1. Search by name: N 
2. Search by extension: E 
3. Search by size: S
\tPlease enter your choice: '''
dir_tools_options = {"n":ui_search_by_name, 
                     "e":ui_search_by_extention, 
                     "s":ui_search_by_size}
error_response = {WindowsError:"Oops! Access denied.", 
                  ValueError:"Enter an numeric value."}
# add number of files for true
files_found_response = {False:"No file(s) found", 
                        True:"{} file(s) found"}
# add filename
file_found_response = {False:"File {} not found",
                       True:"File {} found"}
file_exists_response ={ False:"Path does not exist.", 
                         True:"Path Found"}
# add choice for true
valid_ui_response = {False:"Invalid choice.", 
                      True:"You choose {}."}
line_length = 40
# or you can have a funky pattern like "`-._.-'-._...
line_pad = "*"*line_length 

def my_print(text, *params):
    # len(params) must match the count of "{}" in the text so this will not crash
    # Perhaps add a check to assert this case
    message = text.format(*params)
    offset = line_length/2 - len(message)/2
    if offset > 0 and offset + len(message) < line_length:
        print(line_pad[:offset] + message + line_pad[offset+len(message):])
    # in the case that a line is larger than the formatting, you can just print the line.
    # its gonna look gross regardless
    else:
        print(message)
yes = ("yes", "y","1")
no = ("no", "n", "0")
def ask_yes_no(question):
    answer = ''
    while not answer in yes + no:
        answer = input(question).lower()
        if not answer in yes + no:
            my_print(valid_ui_response[False])
        else:
            my_print(valid_ui_response[True], return_to_menu)
            # True - yes, False - no
            return answer in yes
quit_question = "Quit Dir Tools? "

def dir_tools(file_path):
    if os.path.exists(file_path):
        my_print(file_exists_response[True] )
    else:
        my_print(file_exists_response[False])
        return
    quit_dir_tools = False
    while not quit_dir_tools:
        answer = input(dir_tools_menu).lower()
        if answer not in dir_tools_options:
            my_print(valid_ui_response[False])
        else:
            my_print(valid_ui_response[True],answer)
            dir_tools_options[answer](file_path)
        quit_dir_tools = ask_yes_no(quit_question)
ui_sbn_question = 'Enter file name: '
return_question = "Return to main menu? "

def ui_search_by_name(file_path):
    return_to_menu = False
    while not return_to_menu:
        name = input(ui_sbn_question)
        try:
            sbn_response = search_by_name(name, file_path)
            if not sbn_response:
                my_print(file_found_response[False], name)
            else:
                my_print(file_found_response[True], name)
                # assuming that this isnt a boolean
                my_print(sbn_response)
        except WindowsError:
            my_print(error_response[WindowsError])
        return_to_menu = ask_yes_no(return_question)

Context

StackExchange Code Review Q#47427, answer score: 2

Revisions (0)

No revisions yet.