How do I import a Python module given its relative path?
For example, if dirFoo
contains Foo.py
and dirBar
, and dirBar
contains Bar.py
, how do I import Bar.py
into Foo.py
?
Here's a visual representation:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
wishes to include Bar
, but restructuring the folder hierarchy is not an option.
Call me overly cautious, but I like to make mine more portable because it's unsafe to assume that files will always be in the same place on every computer. Personally I have the code look up the file path first. I use Linux so mine would look like this:
That is of course unless you plan to package these together. But if that's the case you don't really need two separate files anyway.
If you structure your project this way:
Then from Foo.py you should be able to do:
Or:
Per Tom's comment, this does require that the
src
folder is accessible either viasite_packages
or your search path. Also, as he mentions,__init__.py
is implicitly imported when you first import a module in that package/directory. Typically__init__.py
is simply an empty file.This also works, and is much simpler than anything with the
sys
module:I'm not experienced about python, so if there is any wrong in my words, just tell me. If your file hierarchy arranged like this:
module_1.py
defines a function calledfunc_1()
, module_2.py:and you run
python module_2.py
in cmd, it will do run whatfunc_1()
defines. That's usually how we import same hierarchy files. But when you writefrom .module_1 import func_1
inmodule_2.py
, python interpreter will sayNo module named '__main__.module_1'; '__main__' is not a package
. So to fix this, we just keep the change we just make, and move both of the module to a package, and make a third module as a caller to runmodule_2.py
.main.py:
But the reason we add a
.
beforemodule_1
inmodule_2.py
is that if we don't do that and runmain.py
, python interpreter will sayNo module named 'module_1'
, that's a little tricky,module_1.py
is right besidemodule_2.py
. Now I letfunc_1()
inmodule_1.py
do something:that
__name__
records who calls func_1. Now we keep the.
beforemodule_1
, runmain.py
, it will printpackage_1.module_1
, notmodule_1
. It indicates that the one who callsfunc_1()
is at the same hierarchy asmain.py
, the.
imply thatmodule_1
is at the same hierarchy asmodule_2.py
itself. So if there isn't a dot,main.py
will recognizemodule_1
at the same hierarchy as itself, it can recognizepackage_1
, but not what "under" it.Now let's make it a bit complicated. You have a
config.ini
and a module defines a function to read it at the same hierarchy as 'main.py'.And for some unavoidable reason, you have to call it with
module_2.py
, so it has to import from upper hierarchy.module_2.py:Two dots means import from upper hierarchy (three dots access upper than upper,and so on). Now we run
main.py
, the interpreter will say:ValueError:attempted relative import beyond top-level package
. The "top-level package" at here ismain.py
. Just becauseconfig.py
is besidemain.py
, they are at same hierarchy,config.py
isn't "under"main.py
, or it isn't "leaded" bymain.py
, so it is beyondmain.py
. To fix this, the simplest way is:I think that is coincide with the principle of arrange project file hierarchy, you should arrange modules with different function in different folders, and just leave a top caller in the outside, and you can import how ever you want.
Be sure that dirBar has the
__init__.py
file -- this makes a directory into a Python package.In my opinion the best choice is to put __ init __.py in the folder and call the file with
It is not recommended to use sys.path.append() because something might gone wrong if you use the same file name as the existing python package. I haven't test that but that will be ambiguous.