Relative Imports in Python
A relative import specifies the resource to be imported relative to the location of the import statement. There are two types of relative imports: implicit and explicit.
Relative imports make use of dot notation to specify location:
- A single dot means that the module or package referenced is in the same directory as the current location.
- Two dots mean that it is in the parent directory of the current location, in other words the directory above.
- Three dots mean that it is in the grandparent directory, and so on.
One clear advantage of relative imports is that they are quite succinct. Unfortunately, relative imports can be messy, particularly for shared projects where directory structure is likely to change. Relative imports are also not as readable as absolute ones, and it’s not easy to tell the location of the imported resources.
00:00
Now that you know how absolute imports work, it’s time to talk about relative imports. Something to note about relative imports is that these are based off the name of the current module. What this means is that if you run your script, that script’s __name__
is going to become '__main__'
. In this case, any imports into that script need to be absolute imports.
00:23
The benefits from a relative import come from going from resource to resource within a package that is then imported. Because of that, we’ll only show syntax examples of how to do relative imports across the projects
package from the directory from before and we won’t run any actual code. To get started, take a look at module1.py
within the package1/
folder. module2
had function1()
in it.
00:52
Let’s say that you wanted to get function1()
from module2
into module1
.
00:58
With an absolute import, you’d have to do something like from package1.module2 import function1
, which is pretty short but still has quite a bit of typing. Because module1
is already in package1
, you don’t need to define that. You can go ahead and get rid of that.
01:21
And this single period (.
) here will represent the current directory that module1
is in, which is package1
. This becomes an explicit relative import instead of an implicit relative import like this. In an implicit relative import, Python would have to figure out where this module2
is located—and this has been deprecated in Python 3.
01:43
So you have to be explicit about it. Once you find module2
in the current directory, everything is the same after that. Let’s jump over to package2
to take a look at some different examples.
01:56
So I’m going to go to package2/module3
.
02:07
And from here, let’s say you want to import the class1
from the __init__
file. With an absolute import, you’d have to say from package2 import class1
,
02:22
like so. But for a relative import, you just need to have that .
there, because class1
is located within the current package. If you wanted to get to module5
within that subpackage, you could do something similar and just say from .subpackage1.module5 import function2
, which was located there.
02:51
So, that makes sense. It’s pretty similar to what we did in package1
up here. Now let’s say for module3
, you want to up to module2
, which is in package1
, and import function1
.
03:04
This is a little bit different, but relative imports are able to do this. What you would do in this case is say from ..package1.module2 import function1
.
03:21
So before, the single dot (.
) represented the current directory that that import
statement was located in. Two dots (..
) represents the parent directory of that directory.
03:33
If you’re familiar with any Unix operating system and you run an ls -a
command, you’ll see that you have all of your items that are in that directory, but then you also always have a single dot (.
) and two dots (..
) representing the current directory and the parent directory. If you ever need to go further than that, you can add three dots (...
), which will bring you to the grandparent directory.
03:54
So, in this case, it would bring you to imports/
, which does not have package1
, so that would not be valid. So, depending on how your project is laid out, relative imports can really help keep your code concise.
04:07 They do present issues if your directory structure is going to change, as that will break your relative imports. And they tend to be a little less readable.
04:16 It can be a little harder to take a quick look and know exactly where some resource is coming from. Because of this, the advantages of relative imports really come into play if you have a very large project and organize your resources so that ones that work together are located close together.
04:33 Otherwise, try to use absolute imports as much as possible. And that’s it! Now you should have a pretty good idea of how and when to use absolute versus relative imports in your projects.
04:46 These definitely require quite a bit of practice to get comfortable with, so try splitting up your next project both ways and see how they can work out for you. Thanks for watching.
Bartosz Zaczyński RP Team on May 16, 2021
@bogdanchira The names of custom modules must be valid Python identifiers, which roughly translates to alphanumeric names. In plain English, your file names must start with a letter rather than a digit.
To make them accessible from any project, it would probably make the most sense bundling them in a Python library that you could install with pip
.
bogdanchira on May 16, 2021
Thank you, yes - I know that about the files naming convection - I was just making a point.
I found the easiest solution (may have some limitations, but it works) - I have simply copied the .py file in Python\Lib\site-packages folder and I can import it directly in any other Python file.
Become a Member to join the conversation.
bogdanchira on May 15, 2021
Hello,
How can I import a custom 1.py file (by custom I mean a file I did) into another 2.py file. The 1.py and 2.py are on different partitions on the computer, deep within a tree of folders? 1.py has an object in that helps create certain structures I use in other various projects, so is not part of any project itself (therefore it does not make sense to have it in the project file structure), I just use it to speed up certain things in each project I need it