1
00:00:00,630 --> 00:00:02,750
Hi guys and welcome back. In this video,

2
00:00:02,750 --> 00:00:05,663
we're going to talk about relative imports in Python.

3
00:00:05,663 --> 00:00:07,600
This is something that's really confusing

4
00:00:07,600 --> 00:00:10,200
for new Python beginners, and to be honest,

5
00:00:10,200 --> 00:00:11,880
it's a bit weird.

6
00:00:11,880 --> 00:00:14,260
And you're not going to be using them very much at all

7
00:00:14,260 --> 00:00:15,580
but I just wanted to talk about them

8
00:00:15,580 --> 00:00:17,680
so that you all use them precisely

9
00:00:17,680 --> 00:00:19,330
because they work very differently

10
00:00:19,330 --> 00:00:21,540
than what you might expect.

11
00:00:21,540 --> 00:00:24,750
What I've got here is four files now.

12
00:00:24,750 --> 00:00:29,140
I've got code, and mymodule in the same folder.

13
00:00:29,140 --> 00:00:34,140
Then we've got our libs folder that contains mylib.

14
00:00:34,790 --> 00:00:37,150
And then we've got our operations folder

15
00:00:37,150 --> 00:00:39,540
that contains operator.

16
00:00:39,540 --> 00:00:44,493
So code imports mymodule, mymodule imports libs.mylib,

17
00:00:45,470 --> 00:00:49,950
and mylib imports libs.operations.operator.

18
00:00:49,950 --> 00:00:52,290
And each one prints out their name.

19
00:00:52,290 --> 00:00:57,290
So if we press play right now, what you get back is--

20
00:00:57,680 --> 00:00:59,950
Well first of all, something important to note is that--

21
00:00:59,950 --> 00:01:01,170
I may not have mentioned it in the last video,

22
00:01:01,170 --> 00:01:04,010
is that when you run the import,

23
00:01:04,010 --> 00:01:06,130
that immediately jumps into the next file

24
00:01:06,130 --> 00:01:07,180
and starts running it.

25
00:01:07,180 --> 00:01:10,980
So of course, code.py imports mymodule

26
00:01:10,980 --> 00:01:12,820
so that stops code.py from running

27
00:01:12,820 --> 00:01:16,470
and Python jumps to mymodule. This imports mylib.

28
00:01:16,470 --> 00:01:18,440
So this stops running and jumps to mylib.

29
00:01:18,440 --> 00:01:20,250
This imports operator so that stops running

30
00:01:20,250 --> 00:01:23,420
and jumps to operator, and that prints.

31
00:01:23,420 --> 00:01:27,100
Then we go back to mylib and then we print,

32
00:01:27,100 --> 00:01:29,820
then we go back to mymodule, then we print,

33
00:01:29,820 --> 00:01:31,600
then we go back to code and then we print.

34
00:01:31,600 --> 00:01:33,530
So that's why the order here is reversed

35
00:01:33,530 --> 00:01:35,730
from the order in which the files are running.

36
00:01:35,730 --> 00:01:38,250
Code is running first but that prints out last

37
00:01:38,250 --> 00:01:42,200
because of that tree of imports that's going on.

38
00:01:42,200 --> 00:01:44,530
So this is not relative imports.

39
00:01:44,530 --> 00:01:48,600
These are just absolute imports where you have to define

40
00:01:48,600 --> 00:01:50,350
the path that you're importing from.

41
00:01:50,350 --> 00:01:55,180
So here and the path is libs.operations.operator

42
00:01:55,180 --> 00:01:58,640
and we're doing from libs.operations import operator,

43
00:01:58,640 --> 00:02:02,980
or you could do import libs.opererations.operator

44
00:02:02,980 --> 00:02:04,290
if you preferred, although then

45
00:02:04,290 --> 00:02:06,020
you would have to access things like

46
00:02:06,020 --> 00:02:08,980
libs.operations.operator.divide.

47
00:02:08,980 --> 00:02:13,270
If a divide function was defined inside that file,

48
00:02:13,270 --> 00:02:14,103
which it's not.

49
00:02:14,103 --> 00:02:15,910
At the moment, nothing's defined inside these files.

50
00:02:15,910 --> 00:02:17,990
They're just printing out their names.

51
00:02:17,990 --> 00:02:20,870
So that is absolute imports.

52
00:02:20,870 --> 00:02:23,250
Let's talk about relative imports.

53
00:02:23,250 --> 00:02:27,330
A relative import is one that can import

54
00:02:27,330 --> 00:02:31,900
from the current folder that the file is in.

55
00:02:31,900 --> 00:02:36,730
But it cannot import unless there is a folder name

56
00:02:36,730 --> 00:02:39,950
in the import path, in the module path.

57
00:02:39,950 --> 00:02:42,784
So, here's what that means.

58
00:02:42,784 --> 00:02:46,160
Libs.mylib when it prints out the name

59
00:02:46,160 --> 00:02:49,190
you can see that there is a folder inside the import path

60
00:02:49,190 --> 00:02:51,530
that is separated from other things in the path

61
00:02:51,530 --> 00:02:53,390
by a full stop, a period.

62
00:02:53,390 --> 00:02:55,250
So here you've got the libs folder

63
00:02:55,250 --> 00:02:57,370
and inside it you've got the mylib file.

64
00:02:57,370 --> 00:02:58,550
You can tell this is the file

65
00:02:58,550 --> 00:03:02,620
because it's the last thing in the import.

66
00:03:02,620 --> 00:03:05,890
Similarly, the operator.py has the file operator,

67
00:03:05,890 --> 00:03:07,180
that's where we're importing from

68
00:03:07,180 --> 00:03:10,360
and two folders, operations and libs.

69
00:03:10,360 --> 00:03:13,610
So, from these two you can do relative imports

70
00:03:13,610 --> 00:03:15,200
because there is a folder.

71
00:03:15,200 --> 00:03:17,270
From these two you cannot do relative imports

72
00:03:17,270 --> 00:03:19,080
because there's no folder.

73
00:03:19,080 --> 00:03:20,590
So let me show you what happens

74
00:03:20,590 --> 00:03:22,490
if you try to do a relative import

75
00:03:22,490 --> 00:03:24,640
and you don't have a folder.

76
00:03:24,640 --> 00:03:26,470
In order to do a relative import

77
00:03:26,470 --> 00:03:28,680
you need to use the from syntax.

78
00:03:28,680 --> 00:03:33,420
So you can do from .mymodule import divide let's say

79
00:03:33,420 --> 00:03:36,173
and I'm going to just add a divide function here.

80
00:03:38,780 --> 00:03:40,660
So (mumbles) divide function there it doesn't do anything

81
00:03:40,660 --> 00:03:44,220
and we're gonna try to import it from .mymodule.

82
00:03:44,220 --> 00:03:47,080
So what that means is from the current folder

83
00:03:47,080 --> 00:03:51,090
look at the mymodule file and import the divide function.

84
00:03:51,090 --> 00:03:56,090
So that makes sense because mymodule is in the same folder

85
00:03:56,720 --> 00:04:00,200
as code.py. You can see down here they're in the same folder

86
00:04:00,200 --> 00:04:02,160
so they should be fine.

87
00:04:02,160 --> 00:04:04,880
But when you try to do that,

88
00:04:04,880 --> 00:04:09,880
what it does is it tries to import from __main.mymodule.

89
00:04:12,230 --> 00:04:16,270
So as you can see because the name of this file was __main

90
00:04:16,270 --> 00:04:18,270
and it doesn't have a folder,

91
00:04:18,270 --> 00:04:21,890
it tries to import from the current place it's in

92
00:04:21,890 --> 00:04:24,460
and Python won't let you do that.

93
00:04:24,460 --> 00:04:28,120
If you are importing from the file you run,

94
00:04:28,120 --> 00:04:31,300
you can't use relative imports.

95
00:04:31,300 --> 00:04:36,300
Going into mymodule.py you could do from .libs import mylib

96
00:04:37,090 --> 00:04:39,710
and what that's going to do is it's going to try to access

97
00:04:39,710 --> 00:04:43,010
the libs folder inside the current folder,

98
00:04:43,010 --> 00:04:44,980
that's what the dot means.

99
00:04:44,980 --> 00:04:47,523
But again, if you try to run this code,

100
00:04:48,570 --> 00:04:51,370
you're going to get that you attempted a relative import

101
00:04:51,370 --> 00:04:54,830
with no known parent package.

102
00:04:54,830 --> 00:04:58,770
Again, mymodule has no information about the folder it's in

103
00:04:58,770 --> 00:05:01,713
so Python can't do a relative import from it.

104
00:05:02,890 --> 00:05:05,760
I'll show you again these paths here,

105
00:05:05,760 --> 00:05:07,270
because what you've got--

106
00:05:07,270 --> 00:05:10,093
Oh, sorry I'll run code.py so it's the same as before.

107
00:05:11,040 --> 00:05:15,510
What you've got is that mymodule and main

108
00:05:15,510 --> 00:05:17,750
are at the top level.

109
00:05:17,750 --> 00:05:19,580
When you're trying to do a relative import,

110
00:05:19,580 --> 00:05:22,320
what Python's going to do is it's going to remove the file

111
00:05:22,320 --> 00:05:23,870
and it's just going to try to append

112
00:05:23,870 --> 00:05:27,670
whatever you import from into the rest of the import path.

113
00:05:27,670 --> 00:05:31,900
So if we go to mylib and then we do from .operations

114
00:05:31,900 --> 00:05:35,387
import operator, what that's gonna do is it's gonna say,

115
00:05:35,387 --> 00:05:40,120
"Okay, mylib, you are inside libs.mylib."

116
00:05:40,120 --> 00:05:43,140
So, because you're trying to do a relative import,

117
00:05:43,140 --> 00:05:45,140
we're going to remove the file

118
00:05:45,140 --> 00:05:48,090
and we're gonna try to put operations at the end

119
00:05:48,090 --> 00:05:49,070
and import from there.

120
00:05:49,070 --> 00:05:52,180
So here it'll work because it'll do libs.operations

121
00:05:52,180 --> 00:05:54,500
and then it'll import operator from that.

122
00:05:54,500 --> 00:05:57,130
So if I run code.py again,

123
00:05:57,130 --> 00:05:59,030
you can see that it all works fine.

124
00:05:59,030 --> 00:06:01,050
There's no errors whatsoever.

125
00:06:01,050 --> 00:06:05,880
However, if by any reason you want to run your mylib file,

126
00:06:05,880 --> 00:06:08,950
for example to debug it or run some code inside it,

127
00:06:08,950 --> 00:06:11,010
make sure it works or something like that,

128
00:06:11,010 --> 00:06:13,730
you won't be able to because, of course,

129
00:06:13,730 --> 00:06:16,540
this now becomes main, if you run it,

130
00:06:16,540 --> 00:06:19,440
and then you can't use relative imports from inside it.

131
00:06:19,440 --> 00:06:22,180
So, if you are going to use relative imports,

132
00:06:22,180 --> 00:06:25,700
you always have to run the same file at the top level,

133
00:06:25,700 --> 00:06:28,093
otherwise you may encounter some issues.

134
00:06:28,950 --> 00:06:30,203
Going into operator.py,

135
00:06:31,110 --> 00:06:35,660
you can actually do from ..mylib import star, let's say,

136
00:06:35,660 --> 00:06:36,900
and what this does in Python

137
00:06:36,900 --> 00:06:39,640
is it accesses the parent folder.

138
00:06:39,640 --> 00:06:43,800
So again if operator is inside libs.operations,

139
00:06:43,800 --> 00:06:47,120
dot dot is going to try to remove the operation

140
00:06:48,111 --> 00:06:50,120
and go direct to the previous one.

141
00:06:50,120 --> 00:06:54,130
So it'll try to do libs.mylib. That's what the dot dot means

142
00:06:54,130 --> 00:06:57,240
it just skips the parent folder and goes up to the next one.

143
00:06:57,240 --> 00:06:59,810
So, of course in order to do that,

144
00:06:59,810 --> 00:07:02,010
you need to be at least two levels deep.

145
00:07:02,010 --> 00:07:04,950
Otherwise if you try to do that for example from libs.mylib,

146
00:07:04,950 --> 00:07:07,760
you're going to try to skip libs and go to the previous one,

147
00:07:07,760 --> 00:07:10,700
but there is no previous one, so you'll find that error.

148
00:07:10,700 --> 00:07:12,180
So, again in order to do this,

149
00:07:12,180 --> 00:07:14,990
you need to do something like that,

150
00:07:14,990 --> 00:07:17,493
and that you can see works totally fine.

151
00:07:19,040 --> 00:07:22,920
Let's go back to why we didn't print anything else out

152
00:07:22,920 --> 00:07:25,010
when we ran this code because as you can see

153
00:07:25,010 --> 00:07:27,650
this output is exactly identical to the one we had before,

154
00:07:27,650 --> 00:07:30,000
so it seems that this did nothing.

155
00:07:30,000 --> 00:07:32,400
But really what's happened is Python has realised

156
00:07:32,400 --> 00:07:37,010
that libs.mylib had already been imported by mymodule

157
00:07:37,010 --> 00:07:39,520
before we imported operator.

158
00:07:39,520 --> 00:07:41,560
So, it didn't try to import it again.

159
00:07:41,560 --> 00:07:45,490
This just reuses the import that's already on six modules.

160
00:07:45,490 --> 00:07:47,360
So that's why we didn't see any more output.

161
00:07:47,360 --> 00:07:50,480
mylib.py didn't run again when we tried to import this.

162
00:07:50,480 --> 00:07:53,020
It was already in dot modules.

163
00:07:53,020 --> 00:07:55,190
I also wanted to say that at any point in time

164
00:07:55,190 --> 00:07:58,820
if you wanted to import say operator.py from mymodule,

165
00:07:58,820 --> 00:08:01,123
you can do import libs.operations.operator,

166
00:08:02,160 --> 00:08:06,450
or of course, from libs.operations import operator.

167
00:08:06,450 --> 00:08:08,400
You can do that as well.

168
00:08:08,400 --> 00:08:10,620
By the way, this just means import everything

169
00:08:10,620 --> 00:08:13,270
that is inside this path here.

170
00:08:13,270 --> 00:08:15,300
So if there were multiple functions,

171
00:08:15,300 --> 00:08:16,470
you would import them all.

172
00:08:16,470 --> 00:08:18,720
If there's multiple variables defined in there,

173
00:08:18,720 --> 00:08:21,320
you would also import them, and so on.

174
00:08:21,320 --> 00:08:22,860
All right that's everything for this video.

175
00:08:22,860 --> 00:08:25,470
Thank you for joining me. I know this stuff is confusing,

176
00:08:25,470 --> 00:08:29,410
but my advice is to not use relative imports in Python.

177
00:08:29,410 --> 00:08:32,260
They are difficult to understand, they're confusing,

178
00:08:32,260 --> 00:08:35,220
they only work if you always run the same files,

179
00:08:35,220 --> 00:08:37,950
and they won't work if you try to run other files

180
00:08:37,950 --> 00:08:39,830
such as the ones that use relative imports

181
00:08:39,830 --> 00:08:42,290
for debugging or to try things out.

182
00:08:42,290 --> 00:08:45,100
So, don't use them. Use absolute imports instead.

183
00:08:45,100 --> 00:08:47,850
Your life will be much easier, and really,

184
00:08:47,850 --> 00:08:50,030
you're not gonna encounter any problems with that.

185
00:08:50,030 --> 00:08:52,930
So thanks for joining me and I'll see you in the next one.

