среда, 26 марта 2014 г.

Импорт в Python

http://blog.amir.rachum.com/post/63666832095/python-importing

Операция импорт в программе на Python

Существует много способов импортировать пакеты и модули - некоторые типичны и их используют практически в каждом файле программы на Питоне, а некоторые не так хорошо известны.

Cheat Sheet

import foo
import foo.bar
from foo import bar
from foo import bar, baz
from foo import *
from foo import bar as fizz
from .foo import bar
 
foo = __import__("foo")
reload(foo)

Different Ways to Import

import foo
 
В Python это основная форма импорта. Как Python узнает, где искать модуль foo?

When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.pathsys.path is initialized from these locations:
  • the directory containing the input script (or the current directory).
  • PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
  • the installation-dependent default.
If there is a bar object (which could be anything from a function to a submodule) it can be accessed like a member: foo.bar. You can also import several modules in one line by doing import foo, bar, but it is considered good practice to put each import in a single line.
 
from foo import bar

This statement imports bar which could be anything that is declared in the module. It could be a function definition, a class (albeit a not-conventionally-named class) or even a submodule (which make foo a package). Notice that if bar is a submodule of foo, this statement acts as if we simply imported bar (if it was in Python’s search path). This means that a bar object is created, and its type is 'module'. No foo object is created in this statement.

Multiple members of foo can be imported in the same line like so:

from foo import bar, baz
 
The meaning of this is pretty intuitive: it imports both bar and baz from the module foo. bar and baz aren’t neccessarily the same types: baz could be a submodule and bar could be function, for that matter. Unlike importing unrelated modules, it’s perfectly acceptable to import everything from one module in the same line.
 
from foo import *

Sometimes foo contains so many things, that it becomes cumbersome to import them manually. Instead, you can just import * to import them all at the same time.
Don’t do this unless you know what you’re doing!
It may seem convenient to just import * instead of specific members, but it is considered bad practice. The reason is that you are in fact “contaminating” your global namespace. Imagine that you do import * on a package where someone unwittingly declared the following function:
def list():
    raise RuntimeError("I'm rubber, you're glue!")
When you do import *, this list definition will *override* the global, built-in list type and you’ll get very, very unexpected errors.
So it’s always better to know *exactly* what you’re importing. If you’re importing too much stuff from a certain package, you can either just suck it up or just import the package itself (import foo) and use the foo qualifier for every use.
An interesting good use for import * is in Django settings file hierarchy. It’s convenient there because you actually do want to manipulate the global namespace with imported settings.
from foo import bar as fizz
This one is far less common than what we covered so far, but still well known. It acts like from foo import bar, except instead of creating a bar object, it creates a fizz module with the same meaning. There are two main reasons to use this kind of statement: the first is when you’re importing two similarly named objects from two different modules. You then use import as to differentiate them, like so:
from xml import Parser as XmlParser
from json import Parser as JsonParser
 The other reason, which I’ve seen used a few times is when you import a lone-named function (or class) and use it extensively throughout your code and want to shorten its name.
from .foo import bar
Well, this escalated quickly.
This one is pretty rare and a lot of people are completely unaware of it. The only difference in this statement is that it uses a modified search path for modules. Namely, instead of searching the entire PYTHONPATH, it searches in the directory where the importing file lives. So if you have two files called fizz.py and foo.py, you can use this import in fizz, and it will import the correct file, even if you have another foo module in your PYTHONPATH.
What is this good for? Well, sometime you create modules with generic names like common, but you might also have a common package in the base of your project. Instead of giving different names, you can explicitly import the one closest to you.
You can also use this method to load modules from an ancestor in the directory tree by putting several dots. For example, from ..foo import Foo will search one directory up, from ...foo import Foo will search two directories up, etc.
foo = __import__("foo")
Ever wondered how can you import a module dynamically? This is how. Obviously you wouldn’t use it with an explicit string, but rather with a variable of some kind. Also notice that you have to explicitly assign the imported module to a variable, or you won’t have access to its attributes.
reload(foo)
This statement does exactly what it looks like. It reloads the foo module. It’s pretty useful when you have a console open playing with a bit of code you’re tweaking and want to continue without resetting your interpreter.
Note: If you used from foo import bar, it’s not enough to reload foo for bar to update. You need to both reload foo and call from foo import bar again.

Import Loops

An import loop would occur in Python if you import two or more modules in a cycle. For example, it in foo.py you would from bar import Bar and in bar.py you from foo import Foo, you will get an import loop:
Traceback (most recent call last):
  File "foo.py", line 1, in 
    from bar import Bar
  File "q:\Programming\Python\loops\bar.py", line 1, in 
    from foo import Foo
  File "q:\Programming\Python\loops\foo.py", line 1, in 
    from bar import Bar
ImportError: cannot import name Bar
When this happens to you, the solution is usually to move the common objects from foo.py and bar.py to a different file (say common.py). However, sometime there’s actually a real loop of dependencies. For example, a method in Bar needs to create a Foo instance and vice versa. When the dependency is in a limited scope, you should remember that you can use the import command wherever you want. Putting imports at the top of the file is the common convention, but sometimes you can solve import loops by importing in a smaller scope, like in a method definition.

Easter Eggs

What fun would an easter egg be if you didn’t try it by yourself? Try these and have fun!
import antigravity
import this
from __future__ import braces
import __hello__
from __future__ import barry_as_FLUFL

Комментариев нет:

Отправить комментарий

X-Plane 11, 12 - любитель, Фото любитель со стажем

Постоянные читатели

Архив блога