Changing How You Import
In this lesson, you’ll figure out why imports sometimes don’t work. Along the way, you’ll learn:
- How
-m
works differently - How things get added to
PYTHONPATH
- How to fix the
-m
version and use absolute imports
00:00
So, the problem here is that this snake
module is not in the path, right? So, how might we add that then? Yeah, if we kind of scale back a little bit, because we had the exact same code working when we just did python snakesay
without the -m
—Right, okay, becuase this this one works. Right.
00:20
But the -m
doesn’t. Exactly. And this is because the -m
treats the path slightly differently. So, there is a convenience, essentially, when you’re running things that the current directory is put into path. Right. Okay, so when you run python snakesay
, then the current directory gets added to path. Right. And in that case, that is the snakesay
directory, while we do the python -m
, this current directory is just the RealPython
directory, not RealPythonsnakesay
.
00:49
Yes. So, when we run just python snakesay
, the directory that’s added to Python’s path is the snakesay
directory within this, the RealPython
directory that we’re working.
00:59
It’s this directory here. Exactly. With the __main__
and the snake.py
. Yeah, so then, therefore, it finds the snake.py
file. Okay.
01:07
So then, we can find the __main__.py
file, basically, and the snake.py
, which needs the import to actually print the bubble and the snake.
01:16
And then in the -m
version, does something get added to path here? I think on the -m
version, it still adds our current path, but it doesn’t add the snakesay
path, or snakesay
directory, to path. Okay, so it’s not looking at the subdirectories. Right.
01:34
So because snake
from here is kind of within the snakesay
directory, it’s saying, “Okay, I can’t find snake
.” It’s not going, recursively searching in the subdirectories for all the files.
01:45
Correct. Okay, so, how do we fix this? There’s a couple of different ways, and let’s start with the simplest one, I guess, would be that if you go into your code and now because snake
is now part of the snakesay
kind of package, we can say from snakesay import snake
.
02:08 And now we can test it. Now it should run. Here we go.
02:13 Yay. Okay, cool. So, let’s go back to the code for a second.
02:19
So we’re in snakesay
, but at the same time we’re saying from snakesay
, so this code, when it’s running, it’s not sure where it is if we call it with the -m
.
02:32
We have to sort of assume that since we’re calling it from outside of this package, that everything starts from that point. So we have to explicitly say from outside the package, we have to go into the package and get snake
from snakesay
. Yes, and what we’re really doing here is that we’re starting using something called absolute imports. So, our import snake
earlier—typically I’ll just call it local import—it’s technically also an absolute import, but it kind of behaves a little bit differently because it depends on this dynamic path that’s being set. Right.
03:08
It depends on where you’re calling your code from because it will only work if you call it from inside the module in certain ways. But it starts to break when you’re using the -m
flag in other places, whereas this has a more explicit pointer towards the snake
module.
Become a Member to join the conversation.
Stephen Felsher Jr on Nov. 27, 2022
Add the following line of code to
__main__.py
if you want to see how the Python path is affected when invoking your script with the options mentioned in this lesson of the tutorial (“Changing How You Import”).You may also have to comment out the import of
snake
and the function call tosnake.say
to avoid any exceptions.