Enable explicit relative imports in __main__ module.
Project description
Enabling explicit relative imports in main modules the easy way.
For enabling relative import in __main__ module PEP 366 presents a workaround like:
if __name__ == "__main__" and __package__ is None:
__package__ = "my_pkg"
from .foo import bar
With rel_imp you can rewrite it as:
import rel_imp; rel_imp.init()
from .foo import bar
Cleaner, faster and less coupled. (you don’t need to specify the package manually)
Note: In order to use rel_imp the module you are coding must be inside a package or a sub-package.
Why using explicit relative imports?
Python 2 still supports implicit relative import and will be deprecated in Python 3, so you will want to migrate those scripts using implicit relative import to explicit relative import. Check more on the PEP 404.
Explicit relative imports makes your code less coupled. As PEP 328 says:
Several use cases were presented, the most important of which is being able to rearrange the structure of large packages without having to edit sub-packages. In addition, a module inside a package can’t easily import itself without relative imports.
Although it is still a matter of taste. (I personally prefer less code to express the same)
Why running sub-modules as main?
Some reasons:
A submodule can become a command line tool if called as main.
You can have unit test or smoke test within the module.
You simply want to run it without any explicit test to see if at least it imports everything it needs.
Installation and Uninstallation
Install via pip
pip install rel_imp
Remove it with:
pip uninstall rel_imp
Install downloading the file
Download the rel_imp.py in one your Python’s search path.
wget https://raw.githubusercontent.com/joaduo/rel_imp/master/rel_imp.py
Example
Imagine you have 2 modules inside a package called “my_pkg”.
That would be:
my_pkg/__init__.py
my_pkg/math_lib.py
my_pkg/test.py
So in test.py we could have
from .math_lib import factorize
def factorize_and_print(number):
num = factorize(number)
print num
if __name__ == '__main__':
#Small smoke test
factorize_and_print(10)
factorize_and_print(0)
factorize_and_print(-10)
If you do python my_pkg/test.py it will throw an exception because of the relative import at the first line.
So you can use rel_imp to make your code look nicer. Simply do:
import rel_imp; rel_imp.init()
from .math_lib import factorize
It is equivalent as the prior solution but you don’t have to worry about keeping in sync __package__’s value.
You can also use a shorter solution with implicit init() using the relative_import module:
import relative_import
from .math_lib import factorize
How does it work?
It uses the same technique in PEP 366 but __package__’s value is set through dynamic inspection of the stack. To solve the value of __package__ it compares the current __main__’s file with search paths in sys.path - or, optionally, a list of paths given in the settings -.
For example, for a file in /home/user/projects/python/math/my_pkg/test.py given the following paths in sys.path:
[
'/home/user/projects/python/',
'/home/user/projects/python/math/',
'/home/user/projects/python/math/my_pkg/',
]
It will pick the closest path to the __main__’s file that is not the __main__’s file’s directory.
Then the base path use to solve __package__ variable will be /home/user/projects/python/math/
This process is only done once and for the __main__. Succesive calls to rel_imp.init() does nothing.
Disabling rel_imp initialization
You can simply define a environment variable PYTHON_DISABLE_REL_IMP with any value.
Feedback or bugs reporting
File an issue through github’s issue tracking system.
You can optionally contact me at joaduo gmail com.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file rel_imp-0.2.8.tar.gz
.
File metadata
- Download URL: rel_imp-0.2.8.tar.gz
- Upload date:
- Size: 6.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.20.1 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.54.1 CPython/3.8.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 63c47cc403703ea68060b1cc03edbae3b75462bc6fb81f513cc82d84d2443a83 |
|
MD5 | fdc3248e7e28bdebad1c9407fef5c5c2 |
|
BLAKE2b-256 | f816afcd1df90e745651b4b468846b69d97b13b4f2842945497809d6ff02609a |