[Django]-Python (and Django) best import practices

6👍

For me, it’s dependent on the situation. If it’s a uniquely named method/class (i.e., not process() or something like that), and you’re going to use it a lot, then save typing and just do from foo import MyClass.

If you’re importing multiple things from one module, it’s probably better to just import the module, and do module.bar, module.foo, module.baz, etc., to keep the namespace clean.

You also said

It has been said that this form helps avoid circular import errors or at least makes the django import system less fragile. It was pointed out that Django’s own code seems to prefer “from x import y” over “import x”.

I don’t see how one way or the other would help prevent circular imports. The reason is that even when you do from x import y, ALL of x is imported. Only y is brought into the current namespace, but the entire module x is processed. Try out this example:

In test.py, put the following:

def a():
    print "a"

print "hi"

def b():
    print "b"

print "bye"

Then in ‘runme.py’, put:

from test import b

b()

Then just do python runme.py

You’ll see the following output:

hi
bye
b

So everything in test.py was run, even though you only imported b

👤Jay P.

13👍

First, and primary, rule of imports: never ever use from foo import *.

The article is discussing the issue of cyclical imports, which still exists today in poorly-structured code. I dislike cyclical imports; their presence is a strong sign that some module is doing too much, and needs to be split up. If for whatever reason you need to work with code with cyclical imports which cannot be re-arranged, import foo is the only option.

For most cases, there’s not much difference between import foo and from foo import MyClass. I prefer the second, because there’s less typing involved, but there’s a few reasons why I might use the first:

  • The module and class/value have different names. It can be difficult for readers to remember where a particular import is coming from, when the imported value’s name is unrelated to the module.

    • Good: import myapp.utils as utils; utils.frobnicate()
    • Good: import myapp.utils as U; U.frobnicate()
    • Bad: from myapp.utils import frobnicate
  • You’re importing a lot of values from one module. Save your fingers, and reader’s eyes.

    • Bad: from myapp.utils import frobnicate, foo, bar, baz, MyClass, SomeOtherClass, # yada yada

2👍

The advantage of the latter is that the origin of MyClass is more explicit. The former puts MyClass in the current namespace so the code can just use MyClass unqualified. So it’s less obvious to someone reading the code where MyClass is defined.

Leave a comment