How to use python absolute import in package?

When you work on a complicated python project, there are many custom packages. In order to manage these packages and avoid shadowing stardand libary, we intend to use absolute import. But there are something you should be careful when you use it.

Python absolute import

Absolute import

I had been confused for quite a long time about how python absolute import works.

Why should we use absolute import? The rationale maybe:

In Python 2.4 and earlier, if you’re reading a module located inside a package, it is not clear whether

import foo

refers to a top-level module or to another module inside the package. As Python’s library expands, more and more existing package internal modules suddenly shadow standard library modules by accident. It’s a particularly difficult problem inside packages because there’s no way to specify which module is meant. To resolve the ambiguity, it is proposed that foo will always be a module or package reachable from sys.path . This is called an absolute import.

As absolute import includes the namesapce for the imported package, users can also get a better understading for what this package does. And it’s always a good habit to avoid name comflicts in a complicated project.

Use in custom package

Okay, so how to use it? Is there any “hello world” demo I can try it out? I found a changelog(more details) about absolute import when python2.5 distributed, alongside with a easy example:

pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py

main.py is

1
2
3
4
from __future__ import absolute_import
from pkg import string
print(string)
string.sayHello()

Note that we can use from __future__ import absolute_import to obtain absolute import if you are running python2.* .

string.py is

1
2
def sayHello():
print('Hello World!')

and leave __init__.py empty.

When you run python main.py in terminal or in an IDE, it would come across an ERROR, ImportError: No module named pkg. This seems weird, we do exactly as the example says, why doesn’t it work?

There is something not clear with the changelog, or you should have some extra knowledge about python import system. Absolute import actually finds top-level module or package reachable from sys.path. So we ran across ImportError because our custom package path not in the sys.path.

In order to fix this, we can either cd to package folder and run as

python -m pkg.main

or add our custom package to PYTHONPATH. In a big project, I suggest add our package path in .bashrc(.bash_profile in Mac) eg:

export PYTHONPATH="your/project/package/:$PYTHONPATH"

or write a script every time you want to use this package, then source that script.

Additional issue

In addition, there is also something not so right with the changelog as follows:

In Python 2.5, you can switch import’s behaviour to absolute imports using a from future import absolute_import directive. This absolute-import behaviour will become the default in a future version (probably Python 2.7). Once absolute imports are the default, import string will always find the standard library’s version.

import string would point to the string.py file in current foler, and would not import string from standard library. Because absolute import finds top-level module or package reachable from sys.path, and current folder path always the first element in the sys.path. More details you can find in this stackoverflow link.

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器