0

problem

Doing a while loop to validate file extension. If a file extension is not .exe or .bat, ask user input again. I am looking for a solution without using import endswith break functions.

code

format = " "
while file[:-4] != ".bat" and file[:-4] != ".exe":
    format = input("Enter file you like to open: ")
    if format[:-4] == ".bat" or format[:-4] == ".exe":
        callFunction(format)
    else:
        file = input("Enter file you like to open: ")

2 Answers2

3

To follow Asking the user for input until they give a valid response and using os.path.splitext() to extract the file extension:

import os

ALLOWED_EXTENSTIONS = {".bat", ".exe"}
while True:
    filename = input("Enter file you like to open: ")
    extension = os.path.splitext(filename)[1]
    if extension in ALLOWED_EXTENSTIONS:
        break

with open(filename) as f:
    # do smth with f

Without break:

import os

ALLOWED_EXTENSTIONS = {".bat", ".exe"}
extension = None
while extension not in ALLOWED_EXTENSTIONS:
    filename = input("Enter file you like to open: ")
    extension = os.path.splitext(filename)[1]

with open(filename) as f:
    # do smth with f

Without break and without any imports:

ALLOWED_EXTENSTIONS = (".bat", ".exe")
filename = ""
while not filename.endswith(ALLOWED_EXTENSTIONS):
    filename = input("Enter file you like to open: ")

with open(filename) as f:
    # do smth with f

Without break and without any imports and without endswith():

ALLOWED_EXTENSTIONS = {"bat", "exe"}
filename = ""
while filename.rsplit(".",1)[-1] not in ALLOWED_EXTENSTIONS:
    filename = input("Enter file you like to open: ")

with open(filename) as f:
    # do smth with f
Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
1

You don't need a loop

def ask_exe(prompt='Executable file name? '):
    name = input(prompt)
    if name[-4:] in {'.exe', '.bat'}: return name
    return ask_exe(prompt='The name has to end in ".exe" or ".bat", please retry: ')

[no breaks, no imports, almost no code...]

As noted by ShadowRanger my code, that uses set notation for the membership test, is suboptimal for Python versions prior to 3.2. For these older versions using a tuple avoids computing the set at runtime, each and every time the function is executed.

...
    # for python < 3.2
    if name[-4:] in ('.exe', '.bat'): return name
...
Community
  • 1
  • 1
gboffi
  • 22,939
  • 8
  • 54
  • 85
  • @ShadowRanger Your edit was a source of inspiration. tx – gboffi Apr 04 '16 at 21:23
  • Just a heads up, the set literal approach will cost more on older Python; `tuple`s of literals get cached in the per function constant store in all versions of Python, but [membership tests for set literals are only converted to `frozenset`s and stored in the constant store on Python 3.2+](https://docs.python.org/3/whatsnew/3.2.html#optimizations); on 3.1 and earlier (including all 2.x releases), the `set` has to be built every time, then a membership test is performed; saving on the lookup by rebuilding the `set` every time is a net loss. For two elements, the `tuple` is fine even in 3.2+. – ShadowRanger Apr 04 '16 at 21:38
  • @ShadowRanger Thank you for the interest, the discussion and the link. Now the reason of your edit are really clear. I've edited my answer accordingly (well, I hope so...) – gboffi Apr 05 '16 at 07:53