Package: rel-imp
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__isNone:__package__="my_pkg"from.fooimportbarWithrel_impyou can rewrite it as:importrel_imp;rel_imp.init()from.fooimportbarCleaner, faster and less coupled. (you don’t need to specify the package
manually)Note:In order to userel_impthe 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 thePEP
404.Explicit relative imports makes your code less coupled. AsPEP
328says: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 UninstallationInstall via pippip install rel_impRemove it with:pip uninstall rel_impInstall downloading the fileDownload therel_imp.pyin one your Python’s search path.wget https://raw.githubusercontent.com/joaduo/rel_imp/master/rel_imp.pyExampleImagine you have 2 modules inside a package called “my_pkg”.That would be:my_pkg/__init__.pymy_pkg/math_lib.pymy_pkg/test.pySo in test.py we could havefrom.math_libimportfactorizedeffactorize_and_print(number):num=factorize(number)printnumif__name__=='__main__':#Small smoke testfactorize_and_print(10)factorize_and_print(0)factorize_and_print(-10)If you dopython my_pkg/test.pyit will throw an exception because
of the relative import at the first line.So you can userel_impto make your code look nicer. Simply do:importrel_imp;rel_imp.init()from.math_libimportfactorizeIt 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 implicitinit()using therelative_importmodule:importrelative_importfrom.math_libimportfactorizeHow 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.pygiven 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
torel_imp.init()does nothing.Disablingrel_impinitializationYou can simply define a environment variablePYTHON_DISABLE_REL_IMPwith any value.Feedback or bugs reportingFile an issue through github’sissue tracking
system.You can optionally contact me at joaduo gmail com.Related PEPshttp://legacy.python.org/dev/peps/pep-0328/http://legacy.python.org/dev/peps/pep-0366/