PEP 8 exegetics: conditional imports?
davea at ieee.org
Fri Aug 7 22:16:01 CEST 2009
Albert Hopkins wrote:
> On Fri, 2009-08-07 at 16:50 +0000, kj wrote:
>> Conditional imports make sense to me, as in the following example:
>> def foobar(filename):
>> if os.path.splitext(filename) == '.gz':
>> import gzip
>> f = gzip.open(filename)
>> f = file(filename)
>> # etc.
>> And yet, quoth PEP 8:
>> - Imports are always put at the top of the file, just after any module
>> comments and docstrings, and before module globals and constants.
>> ...which seems to condemn conditional imports unequivocally.
>> Then again, the PEP 8 scriptures do not explicitly mention conditional
>> imports at all, as far as I can tell, which leaves open the
>> possibility that they are still righteous.
>> In fact, venerable passages in the Python standard library source
>> code, if properly interpreted, can be seen to carry out conditional
>> imports, such as this fragment recovered from random.py:
>> if a is None:
>> a = long(_hexlify(_urandom(16)), 16)
>> except NotImplementedError:
>> import time
>> a = long(time.time() * 256) # use fractional seconds
>> Or even more clearly, this one from test/pystone.py:
>> if __name__ == '__main__':
>> import sys
> I can't speak for others... but generally you can "tell" when an import
> belongs at the top of a module and when you need to make exceptions. I
> would say that, as a general rule, they go up top (easier to identify
> what external dependencies a module have). There are, of course,
> * Exceptions and other not-often-executed blocks
> * Inside test functions (where the imported modules are only used
> by tests
> * Inside main() functions where the imported modules are only used
> if the module is run as a script
> * When startup-time is important. Often it's necessary to have you
> module up and running in an instant and import "expensive"
> modules as-needed.
> * "Dynamic" import such as plugins, etc.
> Of course, like everything else in PEP 8, it's meant as a "guide" and
> not as an "order". YMMV.
Excellent points. I'd add a couple more, one pro, and two con:
You need conditionals when you're doing things that are
environment-specific. For example, you might use Win32 stuff when on
Windows, and something else when on Linux. So you might have a pair of
modules which encapsulate the non-portable aspects, and conditionally
import one of those.
You usually want any imports to be complete before starting
multithreading. As somebody else has recently pointed out, there's an
import-lock that's active during imports,
If two modules do mutual imports (not a good idea, but it is sometimes
practically unavoidable), the earlier in the file that the import
happens, the less likely for a problem to crop up. So try to put them
at the top.
More information about the Python-list