3

I am confused on how to use Try/Exception and if/else. How can I write idiomatic code if I want to tell the user to provide .html file

if url[-4:] ==".html":
        // do your things
else: 
    print('Error! the file is not html file')

I am checking whether I should use try/exception in such scenarios or if/else as I did.

user3378649
  • 5,154
  • 14
  • 52
  • 76
  • 1
    possible duplicate of [Better to 'try' something and catch the exception or test if its possible first to avoid an exception?](http://stackoverflow.com/questions/7604636/better-to-try-something-and-catch-the-exception-or-test-if-its-possible-first) – kartikg3 Dec 18 '14 at 01:31
  • Well... Exceptions in Python are cheap and can be used as a messaging mechanism. So instead of "printing" you could raise `MyInputException('Error! the file is not html file')` to trigger the code handling the input error. – Paulo Scardine Dec 18 '14 at 01:31
  • You have a problem: url[-4:] is "html" not ".html" so the if will always fail. Also, a user might name the file with type ".htm" and/or they could use upper case. And what if the filename is shorter than 5 characters? – Marichyasana Dec 18 '14 at 01:43

4 Answers4

4

In Python, it's Easier to ask for forgiveness than permission. In other words, the idiomatic way in Python would be to just let the exception be thrown and react accordingly, instead of explicitly checking the condition ("Look before you leap", also in the linked glossary). So your code should look like this:

try:
    # do your thing with `url`
except:
    print('Error! the file is not html file')
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • But how can I specify the condition if url[-4:] ==".html" ? – user3378649 Dec 18 '14 at 01:33
  • @user3378649 of course you can, but the point is: in general you shouldn't. Do your normal stuff, if the file turns out to be something other than an html the error handling code will kick-in. – Óscar López Dec 18 '14 at 01:35
  • 1
    @user3378649 no, if you really want the input to end in ".html" there is no idiomatic way to test it using try/except instead of using `if`. – Paulo Scardine Dec 18 '14 at 01:36
  • 1
    You could keep the try except principle AND use your if check by using the assert statement. It will throw an error when your if fails and your except will catch it. – kartikg3 Dec 18 '14 at 01:41
  • I would not say EAFP always apply; you can use LBYL or EAFP, but compared to most imperative languages EAFP tends to be way cheaper in Python. Use both with discretion. Using EAFP for duck-typing is indeed idiomatic while LBYL tests using `isinstance` are frowned upon. – Paulo Scardine Dec 18 '14 at 02:13
4

In a nutshell:

try:
    a = q.get()

try means try this thing, if it works, use it, else except something else if it fails, or it works, and there is an error such as ValueError.

except:
    a = None

Updated:

try:
   url[-4:] == ".html"

except: 
    print "Error"
Veedrac
  • 58,273
  • 15
  • 112
  • 169
Jonathan Davies
  • 882
  • 3
  • 12
  • 27
  • 1
    This answer is factually wrong. `try: url[-4:] == ".html"` does not throw any exception if the statement is false. – dom0 Dec 18 '14 at 01:49
  • @dom0 in hind side, yes and no, no the `url` isn't getting reassigned in the `except`. But yes, I have explained in the previous example how to properly use the `try` and `except`, which I think user3378649 was looking for. – Jonathan Davies Dec 18 '14 at 01:54
  • warning: Do not overuse EAFP - specially if LBYL is comparatively less expensive - why would you try an expensive operation if a cheap test would work? – Paulo Scardine Dec 18 '14 at 02:32
2

If you want the file name to end in ".html" it is perfectly OK to test using if.

You can also use assert, if you want to bubble up an exception to catch it at code a few levels above:

assert url.lower().endswith(".html"), u"the file name must end in .html"

It is just syntactic sugar for:

if url.lower().endswith(".html"):
    do_your_things_with_url(url)
else: 
    raise YourCustomException('the url must end in ".html"')

Of course it would be silly to replace a simple if test with this:

try:
    assert url.lower().endswith(".html")
except AssertionError:
    print('Error! url does not end in ".html"')
else:
    do_your_things_with_url(url)

So answering your question, you probably should use the if test for testing if the string ends in ".html".

PS: This style is called LBYL (look before you leap) and there is nothing wrong with it in Python. The alternative is the EAFP (easier to ask for forgiveness than permission). Both are OK and considered idiomatic for most situations with a few exceptions (like for example duck-typing, where the EAFP style is clearly favored against LBYL tests using hasattr and/or isinstance). Do not overuse EAFP specially if LBYL is comparatively less expensive - why would you try an expensive operation if a cheap test would work?

Paulo Scardine
  • 73,447
  • 11
  • 124
  • 153
0

Rather than checking the file extension, you would attempt to parse the file as HTML, and then show the user a useful error if an HTML parsing exception happens. For example, using BeautifulSoup and HTMLParser:

from bs4 import BeautifulSoup
from html.parser import HTMLParseError

try:
    BeautifulSoup(fetched_url_contents)
except HTMLParseError:
    print("Error: you haven't given me html!")
Erin Call
  • 1,764
  • 11
  • 15
  • thanks for bring thing on top. this is a question related to the use of Try/except. as I handle verifying html file using that. – user3378649 Dec 18 '14 at 01:39