开发者

Python (and Django) best import practices

开发者 https://www.devze.com 2022-12-10 19:20 出处:网络
Out of the various ways to import code, are there some ways that are preferable to use, compared to others? This link http://effbot.org/zone/import-confusion.htm in short

Out of the various ways to import code, are there some ways that are preferable to use, compared to others? This link http://effbot.org/zone/import-confusion.htm in short states that

from foo.bar import MyClass

is not the preferred way to import MyClass under normal circumstances or unless you know what you are doing. (Rather, a better way would like:

import foo.bar as foobaralias

and then in the code, to access MyClass use

foobaralias.MyClass

)

In short, it seems that the above-referenced link is saying it is usually better to import everything from a module, rather than just parts of the module.

However, that article I linked is really old.

I've also heard that it is better, at least in the context of Django projects, to instead only import the classes you want to use, rather than the whole module. 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开发者_JS百科 own code seems to prefer "from x import y" over "import x".

Assuming the project I am working on doesn't use any special features of __init__.py ... (all of our __init__.py files are empty), what import method should I favor, and why?


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


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消