safay
safay

Reputation: 627

Is it appropriate to raise an EnvironmentError for os.environ?

When os.environ is given the name of an environment variable that is not set, it throws a KeyError:

In [1]: my_value = os.environ['SOME_VALUE']

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-6-0573debe183e> in <module>()
----> 1 my_value = os.environ['SOME_VALUE']

~/blah/ve/lib/python3.6/os.py in __getitem__(self, key)
    667         except KeyError:
    668             # raise KeyError with the original key value
--> 669             raise KeyError(key) from None
    670         return self.decodevalue(value)
    671 

KeyError: 'SOME_VALUE'

I get that a KeyError is raised because os.environ is like a dict, but in an application that needs SOME_VALUE to be set, I want to raise a more informative error when the user has neglected to set it. One option is to raise an EnvironmentError with a more informative message:

try:
    my_value = os.environ['SOME_VALUE']
except KeyError:
    raise EnvironmentError('SOME_VALUE environment variable needs to be set to import this module') from KeyError

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
KeyError: 

The above exception was the direct cause of the following exception:

OSError                                   Traceback (most recent call last)
<ipython-input-10-406772b14ea9> in <module>()
      2     my_value = os.environ['SOME_VALUE']
      3 except KeyError:
----> 4     raise EnvironmentError('SOME_VALUE environment variable not set') from KeyError

OSError: SOME_VALUE environment variable not set

It is curious to me that this raises an OSError. The Python 2.7 documentation says EnvironmentError is the base class for OSError, and that base exceptions "...are only used as base classes for other exceptions." In Python 3.6 documentation, EnvironmentError is listed among concrete exceptions, but without any documentation for the error class itself. Questions:

  1. Is it even appropriate to use EnvironmentError in this case? Should I be using some other built-in error, or maybe a custom error?
  2. Is EnvironmentError a base error class in Python 3.6?
  3. Why does OSError get raised instead of EnvironmentError?

Upvotes: 20

Views: 10047

Answers (2)

Mike T
Mike T

Reputation: 43642

I sense a bit of confusion as to what "EnvironmentError" is. It does not relate to environment variables. The original meaning (in Python 2) for exception EnvironmentError is:

The base class for exceptions that can occur outside the Python system: IOError, OSError.

With PEP 3151, the IO and OS exceptions were re-worked for Python 3.3, such that they all use OSError as a base class. EnvironmentError is kept as an alias of OSError for backwards compatibility.


Some appropriate suggestions for exceptions related to environment variables could be:

  • RuntimeError - this is a bit of a "miscellaneous" exception type, but it is perhaps appropriate if the local running environment does not have the variable set.
  • ValueError - the environment variable is set, but there is an exception with its value.

Upvotes: 12

Michael Spagon
Michael Spagon

Reputation: 151

Why don't you just use

my_value = os.getenv("SOME_VALUE")

It will just return None if it doesn't exist. And if you want, you can throw your own errors.

Upvotes: 0

Related Questions