WEBVTT 1 00:00:00.000 --> 00:00:01.730 Python and welcome bacK. 2 00:00:01.730 --> 00:00:05.460 In this video we're looking at importing our own files. 3 00:00:05.460 --> 00:00:07.030 Importing just means , 4 00:00:07.030 --> 00:00:09.200 allowing a file we're currently working on 5 00:00:09.200 --> 00:00:12.030 to use code defined in some other file. 6 00:00:12.030 --> 00:00:15.210 And we've done this with the JSON module in the last video. 7 00:00:15.210 --> 00:00:18.120 And that just meant we're getting the code in that module, 8 00:00:18.120 --> 00:00:20.040 available for us to use. 9 00:00:20.040 --> 00:00:23.543 Now it's time to import code that we ourselves have written, 10 00:00:24.420 --> 00:00:26.350 that way we will be able to split our programmes 11 00:00:26.350 --> 00:00:27.800 into multiple files, 12 00:00:27.800 --> 00:00:29.850 and that's of course is going to help, 13 00:00:29.850 --> 00:00:32.310 because our programme will have better organisation, 14 00:00:32.310 --> 00:00:33.980 and when it comes to changing it, 15 00:00:33.980 --> 00:00:36.920 and improving it's going to be a bit easier. 16 00:00:36.920 --> 00:00:38.950 Let's start by creating a new file, 17 00:00:38.950 --> 00:00:40.270 inside our Programme project 18 00:00:40.270 --> 00:00:42.400 after the new Python project here. 19 00:00:42.400 --> 00:00:46.350 And I'm going to call it, file operations, 20 00:00:46.350 --> 00:00:48.230 so that's file_operations 21 00:00:48.230 --> 00:00:50.330 run but don't put any spaces in file names, 22 00:00:50.330 --> 00:00:53.250 that's a recipe for disaster in pretty much any computer, 23 00:00:53.250 --> 00:00:55.250 but especially when working with Python. 24 00:00:56.110 --> 00:00:56.980 Now inside this file, 25 00:00:56.980 --> 00:00:58.730 we're gonna write a couple of functions. 26 00:00:58.730 --> 00:01:01.270 One, to save Some content we file, 27 00:01:01.270 --> 00:01:03.820 and the other one to read some content from a file. 28 00:01:04.670 --> 00:01:06.070 So save to file, 29 00:01:06.070 --> 00:01:08.460 the content we wanna write is gonna be a first parameter, 30 00:01:08.460 --> 00:01:10.530 and the file name is gonna be the second parameter, 31 00:01:10.530 --> 00:01:11.640 and all is gonna do, 32 00:01:11.640 --> 00:01:14.210 is use a context manager to open the file 33 00:01:14.210 --> 00:01:15.563 and then write the content. 34 00:01:16.720 --> 00:01:19.120 And then read file is going to be pretty similar 35 00:01:19.120 --> 00:01:21.040 it's gonna take the file name, 36 00:01:21.040 --> 00:01:24.370 and it's going to use a context manager to open the file, 37 00:01:24.370 --> 00:01:27.370 and read the contents out fully as a single string, 38 00:01:27.370 --> 00:01:28.213 and return them. 39 00:01:29.110 --> 00:01:30.610 Now I think you can implement this 40 00:01:30.610 --> 00:01:32.100 knowing what you know already, 41 00:01:32.100 --> 00:01:34.340 and if you have to look at the code for the section 42 00:01:34.340 --> 00:01:37.120 make sure to not look at the import project, 43 00:01:37.120 --> 00:01:38.700 and which is also available on GitHub, 44 00:01:38.700 --> 00:01:41.130 but look at the other files we've already written, 45 00:01:41.130 --> 00:01:43.150 and then implement these functions using, 46 00:01:43.150 --> 00:01:44.720 what you already know. 47 00:01:44.720 --> 00:01:47.060 Don't copy and paste code, just type it out. 48 00:01:47.060 --> 00:01:49.410 And once you've done that come back to the video, 49 00:01:49.410 --> 00:01:51.320 and we shall continue. 50 00:01:51.320 --> 00:01:52.610 I hope you managed, 51 00:01:52.610 --> 00:01:55.720 all we have to do is use a context manager to open 52 00:01:55.720 --> 00:01:59.680 the file name in write mode, 53 00:01:59.680 --> 00:02:00.810 and then what we're going to do 54 00:02:00.810 --> 00:02:03.363 is a file.write content. 55 00:02:04.350 --> 00:02:06.693 Am sorry, of course you need as file in there. 56 00:02:07.610 --> 00:02:09.280 In order to have a variable. 57 00:02:09.280 --> 00:02:10.760 This is optional by the way, 58 00:02:10.760 --> 00:02:12.920 but then you don't have anything pointing to 59 00:02:12.920 --> 00:02:14.230 whatever you've opened, 60 00:02:14.230 --> 00:02:15.640 and then you cannot write to it 61 00:02:15.640 --> 00:02:18.140 if you don't have a variable write points to open. 62 00:02:19.000 --> 00:02:20.350 Then of course for the reading, 63 00:02:20.350 --> 00:02:21.390 we're gonna do open, 64 00:02:21.390 --> 00:02:23.623 or file name but this time in reading mode. 65 00:02:24.760 --> 00:02:27.640 And what we gonna do is return file.read. 66 00:02:27.640 --> 00:02:30.150 Notice how this is not going to give us, 67 00:02:30.150 --> 00:02:32.030 the lines or anything like that, 68 00:02:32.030 --> 00:02:34.760 but this is going to be one long string , 69 00:02:34.760 --> 00:02:37.563 that could contain things like this. 70 00:02:40.110 --> 00:02:44.072 See, now if we wanted lines after it, 71 00:02:44.072 --> 00:02:47.370 we can split on the backslash, 72 00:02:47.370 --> 00:02:50.680 and .split on backslash, 73 00:02:50.680 --> 00:02:55.680 and it's going to give us something like this Rolf, Charlie, 74 00:02:55.800 --> 00:02:57.310 and so forth. 75 00:02:57.310 --> 00:02:58.900 So this is going to give us one long string, 76 00:02:58.900 --> 00:03:01.440 we can then split it into a lines if we want. 77 00:03:01.440 --> 00:03:03.950 If your file is extremely long, 78 00:03:03.950 --> 00:03:04.980 you may have some problems 79 00:03:04.980 --> 00:03:07.580 with reading the entire file at once. 80 00:03:07.580 --> 00:03:10.063 But let's forget about this problem for now. 81 00:03:11.191 --> 00:03:13.110 Look at some relatively simple stuff, 82 00:03:13.110 --> 00:03:14.680 writing to a file and reading from it, 83 00:03:14.680 --> 00:03:15.980 We've already done this. 84 00:03:15.980 --> 00:03:17.350 But it's going to be useful as an example 85 00:03:17.350 --> 00:03:18.790 to look into importing, 86 00:03:18.790 --> 00:03:19.800 and in deed, 87 00:03:19.800 --> 00:03:23.723 this is essentially our first library. 88 00:03:24.780 --> 00:03:27.890 This library, we're going to import these two files, 89 00:03:27.890 --> 00:03:28.940 these two functions, 90 00:03:28.940 --> 00:03:31.520 and we're going to now very easily save things to a file, 91 00:03:31.520 --> 00:03:32.720 and read them from a file, 92 00:03:32.720 --> 00:03:35.670 without having to worry about opening them. 93 00:03:35.670 --> 00:03:37.940 Let's create a new file in our imports project 94 00:03:37.940 --> 00:03:39.033 called app.py. 95 00:03:40.600 --> 00:03:42.880 And now we're going to import, 96 00:03:42.880 --> 00:03:44.933 the things from file operations. 97 00:03:46.560 --> 00:03:48.220 There are two ways that we can do that. 98 00:03:48.220 --> 00:03:50.763 First one is we can import file operations. 99 00:03:51.850 --> 00:03:54.987 And then we can do file_operations.save_to_file 100 00:03:56.722 --> 00:03:58.540 whatever you want to say Rolf, 101 00:03:58.540 --> 00:04:02.480 and data.txt, for example. 102 00:04:02.480 --> 00:04:07.070 We can do this, call the fiLe operations module. 103 00:04:07.070 --> 00:04:10.123 Whenever you import something, by the way, 104 00:04:11.220 --> 00:04:15.350 the thing you're importing is now called a module. 105 00:04:15.350 --> 00:04:18.320 And it is executed in module mode, 106 00:04:18.320 --> 00:04:20.740 which is essentially the same as executing it 107 00:04:20.740 --> 00:04:23.890 in normal mode, or script mode 108 00:04:23.890 --> 00:04:26.710 but there are some minor differences 109 00:04:26.710 --> 00:04:28.200 that we're gonna look at in a moment. 110 00:04:28.200 --> 00:04:31.070 So whenever you import something ,that's a module, 111 00:04:31.070 --> 00:04:32.500 Whenever you're running something like 112 00:04:32.500 --> 00:04:33.990 if you run app.py 113 00:04:33.990 --> 00:04:35.610 that's called a script. 114 00:04:35.610 --> 00:04:37.590 Okay, normally you're have one script 115 00:04:37.590 --> 00:04:38.730 that's app py , 116 00:04:38.730 --> 00:04:40.050 and a bunch of modules, 117 00:04:40.050 --> 00:04:42.780 and that's everything else that you import. 118 00:04:42.780 --> 00:04:44.090 File operations is the module, 119 00:04:44.090 --> 00:04:46.840 and then we're accessing inside of it with a dot, 120 00:04:46.840 --> 00:04:48.810 then save to file function. 121 00:04:48.810 --> 00:04:51.340 And to which we gave the two arguments that it needs, 122 00:04:51.340 --> 00:04:53.220 the content that we wanna save, 123 00:04:53.220 --> 00:04:55.630 and the file name. 124 00:04:55.630 --> 00:04:58.740 So let's right click app.py and run it. 125 00:04:58.740 --> 00:05:00.010 Notice how nothing happens, 126 00:05:00.010 --> 00:05:03.110 but data.txt does get created, 127 00:05:03.110 --> 00:05:04.560 and Rolf is in it. 128 00:05:04.560 --> 00:05:06.870 This file has been closed as well, 129 00:05:06.870 --> 00:05:09.670 because the save to file function in file operations 130 00:05:09.670 --> 00:05:11.230 has this context manager, 131 00:05:11.230 --> 00:05:13.720 which closes the file at the end. 132 00:05:13.720 --> 00:05:15.100 So this is pretty cool. 133 00:05:15.100 --> 00:05:17.790 I mean, in a single line now, 134 00:05:17.790 --> 00:05:19.680 because we've got our library here, 135 00:05:19.680 --> 00:05:22.260 we are opening, saving and closing the file 136 00:05:22.260 --> 00:05:25.123 without having to worry about doing that manually. 137 00:05:26.730 --> 00:05:27.563 The other option, 138 00:05:27.563 --> 00:05:29.430 I said there were two options for importing, 139 00:05:29.430 --> 00:05:34.430 is to do from file operations import save to file, 140 00:05:34.600 --> 00:05:37.340 and then the save to file is what becomes 141 00:05:37.340 --> 00:05:39.950 the globally available thing in this script, 142 00:05:39.950 --> 00:05:41.423 and you can just run back, 143 00:05:42.520 --> 00:05:44.150 save to file directly. 144 00:05:44.150 --> 00:05:45.900 Of course, this is not so good 145 00:05:45.900 --> 00:05:47.940 if you're importing from many places, 146 00:05:47.940 --> 00:05:50.050 and two things have the same name. 147 00:05:50.050 --> 00:05:51.200 It can happen, 148 00:05:51.200 --> 00:05:53.240 then of course Python will be very confused, 149 00:05:53.240 --> 00:05:55.200 and you would only ever be able to use 150 00:05:55.200 --> 00:05:57.660 the one you import last. 151 00:05:57.660 --> 00:05:59.800 So if you have things with multiple, 152 00:05:59.800 --> 00:06:01.290 multiple things with the same name, 153 00:06:01.290 --> 00:06:04.370 use the former import file operations, 154 00:06:04.370 --> 00:06:05.860 if you only have a couple of things 155 00:06:05.860 --> 00:06:07.210 that you wanna import and use, 156 00:06:07.210 --> 00:06:09.650 feel free to import them like this. 157 00:06:09.650 --> 00:06:10.870 But at the end of the day it's up to you, 158 00:06:10.870 --> 00:06:12.620 whatever you feel is more readable. 159 00:06:14.130 --> 00:06:16.920 Now, we can also have a comma after it, 160 00:06:16.920 --> 00:06:20.520 and import write to file or read file, sorry, 161 00:06:20.520 --> 00:06:23.340 save to file is write to file same thing read file, 162 00:06:23.340 --> 00:06:27.770 and then we can print the read file of data.txt. 163 00:06:27.770 --> 00:06:29.500 Let's run that again, 164 00:06:29.500 --> 00:06:32.260 and now we get Rolf printed out down here at the bottom, 165 00:06:32.260 --> 00:06:34.480 because we've saved Rolf to data.txt, 166 00:06:34.480 --> 00:06:36.510 and then we've read it and print it out, 167 00:06:36.510 --> 00:06:38.800 notice when the file is opened and then closed, 168 00:06:38.800 --> 00:06:41.113 and opened and then closed in every function. 169 00:06:43.660 --> 00:06:45.120 Now in a larger application, 170 00:06:45.120 --> 00:06:48.030 we would start separating our files into folders , 171 00:06:48.030 --> 00:06:49.790 so that things are more organised, 172 00:06:49.790 --> 00:06:51.940 and it's easier to find what we need. 173 00:06:51.940 --> 00:06:55.550 If all your Python files potentially many 100s of them 174 00:06:55.550 --> 00:06:58.470 would be in the same import project folder, 175 00:06:58.470 --> 00:07:00.100 you would have a lot of trouble 176 00:07:00.100 --> 00:07:01.880 finding the things you want, 177 00:07:01.880 --> 00:07:03.930 and it would get very messy very quickly. 178 00:07:05.030 --> 00:07:08.253 So instead, you normally would create a new directory, 179 00:07:09.210 --> 00:07:12.550 and I'm gonna call it something like utils for utilities, 180 00:07:12.550 --> 00:07:15.663 file operations is gonna be part of such utilities. 181 00:07:16.910 --> 00:07:19.315 Let's drag file operations into utils, 182 00:07:19.315 --> 00:07:22.350 and if you get asked to search for references, 183 00:07:22.350 --> 00:07:24.110 make sure to not check it, 184 00:07:24.110 --> 00:07:26.500 for that is going to completely moot the point 185 00:07:26.500 --> 00:07:28.100 that I'm about to show you. 186 00:07:28.100 --> 00:07:30.420 So don't search for references and press okay. 187 00:07:31.780 --> 00:07:33.860 Now we see a couple of things. 188 00:07:33.860 --> 00:07:36.280 File operations has moved into utils, 189 00:07:36.280 --> 00:07:38.540 and red lines have appeared everywhere. 190 00:07:38.540 --> 00:07:41.310 Of course, this is now an unresolved reference, 191 00:07:41.310 --> 00:07:43.740 it doesn't know what final operations is, 192 00:07:43.740 --> 00:07:47.323 because it's no longer in the same directory as app.py. 193 00:07:48.420 --> 00:07:51.020 In fact, I'll even go as far as saying 194 00:07:51.020 --> 00:07:54.320 it's not in the same directory imports project 195 00:07:54.320 --> 00:07:57.460 which is the top level directory of our project. 196 00:07:57.460 --> 00:07:59.230 So you can only do this 197 00:07:59.230 --> 00:08:01.650 from file operations import something, 198 00:08:01.650 --> 00:08:05.210 if file operations is a module available 199 00:08:05.210 --> 00:08:07.503 on the top level of your project. 200 00:08:08.450 --> 00:08:09.960 Okay? 201 00:08:09.960 --> 00:08:11.980 Because now it's inside details, 202 00:08:11.980 --> 00:08:13.440 we cannot do this, 203 00:08:13.440 --> 00:08:15.968 so what can we do? 204 00:08:15.968 --> 00:08:19.460 Well, we can run the file first of all, 205 00:08:19.460 --> 00:08:21.790 to see that we get a module not found error, 206 00:08:21.790 --> 00:08:23.500 just wanted to show you that this is what you get, 207 00:08:23.500 --> 00:08:26.090 if you import something that doesn't exist. 208 00:08:26.090 --> 00:08:27.863 And we must do two things. 209 00:08:29.060 --> 00:08:31.680 We must first of all, 210 00:08:31.680 --> 00:08:34.120 give Python the full path to import, 211 00:08:34.120 --> 00:08:36.760 starting from the top level folder, 212 00:08:36.760 --> 00:08:39.400 so the full path is utils, 213 00:08:39.400 --> 00:08:42.780 and inside utils we've got file operations. 214 00:08:42.780 --> 00:08:43.733 So utils, 215 00:08:44.700 --> 00:08:46.920 and inside utils and we say dot, 216 00:08:46.920 --> 00:08:48.683 we've got file operations. 217 00:08:49.890 --> 00:08:50.920 There we have it. 218 00:08:50.920 --> 00:08:52.270 Now we've got utils, 219 00:08:52.270 --> 00:08:53.980 inside file operations, 220 00:08:53.980 --> 00:08:55.530 we can import these two things. 221 00:08:56.400 --> 00:08:57.653 Now it works. 222 00:08:59.350 --> 00:09:00.950 Frequently though, 223 00:09:00.950 --> 00:09:05.190 is a good idea to tell Python that the utils package, 224 00:09:05.190 --> 00:09:09.660 the utils directory here is actually a Python package, 225 00:09:09.660 --> 00:09:10.780 and I'm not sure if, 226 00:09:10.780 --> 00:09:12.970 actually not sure if this has changed recently in Python, 227 00:09:12.970 --> 00:09:15.800 but it's used to be that you would have to tell python, 228 00:09:15.800 --> 00:09:17.763 this is a Python package. 229 00:09:18.600 --> 00:09:20.840 Before you could import things from it, 230 00:09:20.840 --> 00:09:23.080 and maybe it's no longer required but nonetheless, 231 00:09:23.080 --> 00:09:25.180 for compliance with previous Python versions 232 00:09:25.180 --> 00:09:29.000 it's always a good idea to tell Python that this folder, 233 00:09:29.000 --> 00:09:31.160 this directory is a Python package, 234 00:09:31.160 --> 00:09:34.220 and it's a folder where Python files live, 235 00:09:34.220 --> 00:09:36.880 and where you want to import. 236 00:09:36.880 --> 00:09:38.410 The way to do that is to right click it, 237 00:09:38.410 --> 00:09:40.070 and create a new Python file, 238 00:09:40.070 --> 00:09:42.120 and it must be called __init__.py 239 00:09:46.322 --> 00:09:47.608 that's two underscore at the start, 240 00:09:47.608 --> 00:09:51.140 two underscores at the end.py. 241 00:09:51.140 --> 00:09:51.973 You can close on file 242 00:09:51.973 --> 00:09:53.950 for we do not need to write anything in it, 243 00:09:53.950 --> 00:09:55.990 but this is just what you should do, 244 00:09:55.990 --> 00:09:58.453 for compliance with older Python versions. 245 00:09:59.527 --> 00:10:00.360 You're Okay? 246 00:10:02.200 --> 00:10:07.170 So now this directory here is called a package, 247 00:10:07.170 --> 00:10:09.980 so that Python knows that it can import things from there, 248 00:10:09.980 --> 00:10:11.990 at least in older versions, okay? 249 00:10:11.990 --> 00:10:15.180 And this is how you gave the full path to Python, 250 00:10:15.180 --> 00:10:19.703 so that it knows where to look for your files. 251 00:10:21.330 --> 00:10:22.280 So that's it for this video, 252 00:10:22.280 --> 00:10:24.370 we've looked at importing our own files, 253 00:10:24.370 --> 00:10:27.470 We're gonna look at relative imports in the very next video, 254 00:10:27.470 --> 00:10:28.370 now see you there.