1 00:00:05,239 --> 00:00:07,259 [music] 2 00:00:09,825 --> 00:00:11,845 [music] 3 00:00:15,440 --> 00:00:17,840 Okay, everyone, welcome to ballroom 2 4 00:00:17,840 --> 00:00:19,359 again. I hope you enjoyed your first 5 00:00:19,359 --> 00:00:21,520 session. The second session is about to 6 00:00:21,520 --> 00:00:24,160 start and I would like you to all give a 7 00:00:24,160 --> 00:00:26,880 warm welcome to someone who is familiar 8 00:00:26,880 --> 00:00:29,039 to many of you and been in the in in 9 00:00:29,039 --> 00:00:30,560 this place for a lot longer than I have. 10 00:00:30,560 --> 00:00:32,719 This is my first pyon. Um give an 11 00:00:32,719 --> 00:00:35,370 applause to Alyssa. 12 00:00:35,370 --> 00:00:37,390 [applause] 13 00:00:42,640 --> 00:00:45,680 Hey. Whoa. 14 00:00:45,680 --> 00:00:48,399 Uh yeah. So Lisa, I started working on 15 00:00:48,399 --> 00:00:50,239 the import system more than two decades 16 00:00:50,239 --> 00:00:52,160 ago. Uh when I contributed the first 17 00:00:52,160 --> 00:00:54,559 version of the -ashm switch for Python 18 00:00:54,559 --> 00:00:56,079 2.4 19 00:00:56,079 --> 00:00:58,399 uh subsequently became a core developer 20 00:00:58,399 --> 00:00:59,600 uh and started contributing to the 21 00:00:59,600 --> 00:01:01,359 import system and interpreter startup 22 00:01:01,359 --> 00:01:04,159 config process more generally and along 23 00:01:04,159 --> 00:01:05,920 with wearing assorted other hats around 24 00:01:05,920 --> 00:01:08,000 the Python community uh I remain the 25 00:01:08,000 --> 00:01:10,400 lead developer for the runpie standard 26 00:01:10,400 --> 00:01:12,320 library module that powers the modern 27 00:01:12,320 --> 00:01:16,159 incarnation of the -m switch. Now, let's 28 00:01:16,159 --> 00:01:19,200 get started. 29 00:01:19,200 --> 00:01:21,520 Sometimes we get failures that simply 30 00:01:21,520 --> 00:01:23,600 don't make any sense. The [snorts] code 31 00:01:23,600 --> 00:01:25,920 our text editor or repository browser is 32 00:01:25,920 --> 00:01:28,159 showing us just isn't consistent with 33 00:01:28,159 --> 00:01:29,360 the behavior that we're seeing at 34 00:01:29,360 --> 00:01:30,960 runtime. 35 00:01:30,960 --> 00:01:33,360 Now, one of the reasons this can happen 36 00:01:33,360 --> 00:01:35,439 is that the code we're looking at isn't 37 00:01:35,439 --> 00:01:37,680 actually the code that's running. Uh, 38 00:01:37,680 --> 00:01:39,520 and one of the ways that can happen is 39 00:01:39,520 --> 00:01:41,439 for the import system to be doing 40 00:01:41,439 --> 00:01:43,680 something that we simply didn't expect. 41 00:01:43,680 --> 00:01:45,759 Now, Python's import system is powerful 42 00:01:45,759 --> 00:01:47,840 and flexible, but it's that very 43 00:01:47,840 --> 00:01:50,720 powerful flexibility that means that 44 00:01:50,720 --> 00:01:52,720 even in its default configuration, it 45 00:01:52,720 --> 00:01:55,920 has the ability to surprise us. 46 00:01:55,920 --> 00:01:58,079 Now, I'm going to spend most of today 47 00:01:58,079 --> 00:01:59,920 diving into assorted technical details 48 00:01:59,920 --> 00:02:01,520 about how the import system is 49 00:02:01,520 --> 00:02:03,520 initialized on startup, some of the ways 50 00:02:03,520 --> 00:02:05,759 that can cause us problems, and various 51 00:02:05,759 --> 00:02:07,119 tools in the standard library and 52 00:02:07,119 --> 00:02:08,640 reference interpreter that let us poke 53 00:02:08,640 --> 00:02:10,479 and prod the import system to determine 54 00:02:10,479 --> 00:02:12,720 what it is actually doing. 55 00:02:12,720 --> 00:02:15,120 However, I'm also going to emphasize two 56 00:02:15,120 --> 00:02:17,200 features up front. Isolated mode and 57 00:02:17,200 --> 00:02:18,800 virtual environments with the system 58 00:02:18,800 --> 00:02:21,280 site packages disabled. While these two 59 00:02:21,280 --> 00:02:23,200 features don't fix all potential import 60 00:02:23,200 --> 00:02:25,599 system configuration problems, they do 61 00:02:25,599 --> 00:02:27,599 disable most of the potential sources of 62 00:02:27,599 --> 00:02:29,040 variability that I'm going to be talking 63 00:02:29,040 --> 00:02:30,959 about today. So, you should see far 64 00:02:30,959 --> 00:02:34,400 fewer, but it works on my machines 65 00:02:34,400 --> 00:02:36,800 uh type problems. 66 00:02:36,800 --> 00:02:39,040 And but the one of the other aspects of 67 00:02:39,040 --> 00:02:41,280 the tech techniques I'm going to be 68 00:02:41,280 --> 00:02:43,360 describing is that for them to be 69 00:02:43,360 --> 00:02:45,280 particularly effective, we need to know 70 00:02:45,280 --> 00:02:48,080 what normal looks like uh in order to 71 00:02:48,080 --> 00:02:51,200 determine when things aren't normal. 72 00:02:51,200 --> 00:02:53,440 If we're always using isolated virtual 73 00:02:53,440 --> 00:02:55,760 environments, then the normal cases that 74 00:02:55,760 --> 00:02:57,760 we need to care about are quite narrowly 75 00:02:57,760 --> 00:03:00,160 defined and that means there's less for 76 00:03:00,160 --> 00:03:03,120 us to learn in order to diagnose the 77 00:03:03,120 --> 00:03:06,159 failures that can still happen. 78 00:03:06,159 --> 00:03:08,640 Now, if we're not using isolated virtual 79 00:03:08,640 --> 00:03:10,319 environments, 80 00:03:10,319 --> 00:03:12,080 well, [laughter] 81 00:03:12,080 --> 00:03:15,360 there's a reason this XKCD exists. 82 00:03:15,360 --> 00:03:17,519 It'd be nice if we only ever had to deal 83 00:03:17,519 --> 00:03:19,360 with pristine virtual environments 84 00:03:19,360 --> 00:03:20,879 constructed from full transitive 85 00:03:20,879 --> 00:03:22,720 dependency trees saved in a lock file 86 00:03:22,720 --> 00:03:25,200 under source control. But in practice, 87 00:03:25,200 --> 00:03:27,200 the real world often isn't as neat as we 88 00:03:27,200 --> 00:03:30,319 would like it to be. developer laptops, 89 00:03:30,319 --> 00:03:32,799 local workstations, shared environments 90 00:03:32,799 --> 00:03:35,280 on stateful production servers, long 91 00:03:35,280 --> 00:03:37,280 live CI servers that don't clean up 92 00:03:37,280 --> 00:03:39,360 properly between runs or are just cing 93 00:03:39,360 --> 00:03:41,599 things that maybe we wish they wouldn't. 94 00:03:41,599 --> 00:03:43,760 Um, there's still plenty of situations 95 00:03:43,760 --> 00:03:45,200 where we have to deal with Python 96 00:03:45,200 --> 00:03:47,200 environments that aren't as pristine as 97 00:03:47,200 --> 00:03:49,280 we might like. 98 00:03:49,280 --> 00:03:51,760 So, if you've seen admonitions to use a 99 00:03:51,760 --> 00:03:54,080 virtual environment, very common, or use 100 00:03:54,080 --> 00:03:55,840 isolated mode, less common, but it still 101 00:03:55,840 --> 00:03:57,840 happens in Python tutorials and app 102 00:03:57,840 --> 00:03:59,439 deployment guides, [snorts] but the 103 00:03:59,439 --> 00:04:02,159 authors haven't delved into why that's a 104 00:04:02,159 --> 00:04:05,120 good idea. The fact those two features 105 00:04:05,120 --> 00:04:07,360 avoid most of the problems I'm talking 106 00:04:07,360 --> 00:04:12,159 about today, that's a big part of it. 107 00:04:12,159 --> 00:04:15,439 So, where will the import system 108 00:04:15,439 --> 00:04:18,079 actually look for modules? If you only 109 00:04:18,079 --> 00:04:20,959 remember one command from this talk, 110 00:04:20,959 --> 00:04:24,960 python-m site is the one. So well this 111 00:04:24,960 --> 00:04:27,120 CLI invocation displays a few pieces of 112 00:04:27,120 --> 00:04:29,280 information. The one we care about for 113 00:04:29,280 --> 00:04:30,960 the purpose of this talk is going to be 114 00:04:30,960 --> 00:04:33,840 a pretty printed list of cy.path entries 115 00:04:33,840 --> 00:04:35,280 with the right background knowledge 116 00:04:35,280 --> 00:04:37,440 which this will hopefully get you some 117 00:04:37,440 --> 00:04:40,000 way towards towards having that 118 00:04:40,000 --> 00:04:42,000 knowledge. The list of directories that 119 00:04:42,000 --> 00:04:43,520 it prints tells us not only the Python 120 00:04:43,520 --> 00:04:45,040 interpreter version where the 121 00:04:45,040 --> 00:04:46,720 interpreter is installed, whether we're 122 00:04:46,720 --> 00:04:48,000 running in an activated virtual 123 00:04:48,000 --> 00:04:52,080 environment, and more. Uh so in the 124 00:04:52,080 --> 00:04:53,360 specific examples today, that 125 00:04:53,360 --> 00:04:55,040 information is somewhat redundant as 126 00:04:55,040 --> 00:04:56,240 you'll be able to see the actual 127 00:04:56,240 --> 00:04:57,440 commands that are setting up the 128 00:04:57,440 --> 00:04:59,520 environments that we're describing. Um 129 00:04:59,520 --> 00:05:01,680 but in the real world with SIM links and 130 00:05:01,680 --> 00:05:03,840 various other things, 131 00:05:03,840 --> 00:05:05,360 this is often a way to find out 132 00:05:05,360 --> 00:05:08,160 information that about the environment 133 00:05:08,160 --> 00:05:09,600 that we may not be able to figure out 134 00:05:09,600 --> 00:05:12,000 other ways. and it can get us started 135 00:05:12,000 --> 00:05:13,520 down to the path of figuring out what's 136 00:05:13,520 --> 00:05:16,400 actually going on. So, what does that 137 00:05:16,400 --> 00:05:20,759 output actually look like? 138 00:05:21,759 --> 00:05:25,400 Whoops, spoilers. 139 00:05:25,600 --> 00:05:29,680 Um, so yeah. So, simplest case, we're 140 00:05:29,680 --> 00:05:32,080 going to run in a virtual environment 141 00:05:32,080 --> 00:05:34,800 uh and we'll be running in isolated 142 00:05:34,800 --> 00:05:38,160 mode. So, there we go. We have our 143 00:05:38,160 --> 00:05:40,160 CIS.path. path. 144 00:05:40,160 --> 00:05:43,520 People can read that. 145 00:05:43,520 --> 00:05:48,560 Good. Um, so we can see up here we have 146 00:05:48,560 --> 00:05:50,479 these are all standard library locations 147 00:05:50,479 --> 00:05:51,919 where standard library modules may be 148 00:05:51,919 --> 00:05:54,240 located and we can see in our virtual 149 00:05:54,240 --> 00:05:57,120 environment here we can see the packages 150 00:05:57,120 --> 00:05:58,240 that are installed in that virtual 151 00:05:58,240 --> 00:06:00,160 environment. Now this is what it looks 152 00:06:00,160 --> 00:06:02,000 like on Linux. If you're on Windows, Mac 153 00:06:02,000 --> 00:06:04,160 OSS, well actually this will look pretty 154 00:06:04,160 --> 00:06:06,400 similar on Mac OS. Standard library is 155 00:06:06,400 --> 00:06:09,120 probably in a different place. um 156 00:06:09,120 --> 00:06:10,880 Windows you'll have Windows paths rather 157 00:06:10,880 --> 00:06:15,840 than pix ones. Um but this command 158 00:06:15,840 --> 00:06:20,080 generally applicable on any uh uh any 159 00:06:20,080 --> 00:06:24,479 platform. Now isolated mode doesn't just 160 00:06:24,479 --> 00:06:30,800 turn off um doesn't just turn off the 161 00:06:30,800 --> 00:06:33,600 path configuration details. One of the 162 00:06:33,600 --> 00:06:37,680 other effects it does is [snorts] 163 00:06:37,680 --> 00:06:40,000 it says we're not running in a trusted 164 00:06:40,000 --> 00:06:42,000 environment and so if we start trying to 165 00:06:42,000 --> 00:06:46,479 play environment games it'll ignore us. 166 00:06:46,479 --> 00:06:48,479 So we're in isolated mode user 167 00:06:48,479 --> 00:06:49,440 environment's not considered 168 00:06:49,440 --> 00:06:53,120 trustworthy. So 169 00:06:53,120 --> 00:06:55,600 we don't need to worry about Python path 170 00:06:55,600 --> 00:06:58,880 messing with us either. So what happens 171 00:06:58,880 --> 00:07:02,400 if we turn off isolated mode? So we'll 172 00:07:02,400 --> 00:07:04,800 stay in our 173 00:07:04,800 --> 00:07:08,080 virtual environment. What's changed? 174 00:07:08,080 --> 00:07:10,639 What's changed is our current working 175 00:07:10,639 --> 00:07:13,599 directory shown up. So any directories 176 00:07:13,599 --> 00:07:16,960 any any modules in our current directory 177 00:07:16,960 --> 00:07:19,680 uh are now visible. This is going to be 178 00:07:19,680 --> 00:07:23,120 important later. Uh 179 00:07:23,120 --> 00:07:25,039 and so yeah and so because we're running 180 00:07:25,039 --> 00:07:27,280 with the dash m switch that has added 181 00:07:27,280 --> 00:07:29,840 the current working directory. Uh if we 182 00:07:29,840 --> 00:07:32,319 use - c that will also add the current 183 00:07:32,319 --> 00:07:35,199 working directory. If we run a direct if 184 00:07:35,199 --> 00:07:39,520 we run a regular python script uh it 185 00:07:39,520 --> 00:07:42,240 will add in isolated mode it won't do 186 00:07:42,240 --> 00:07:44,800 anything. Uh in nonisolated mode it will 187 00:07:44,800 --> 00:07:48,160 add the directory that the script is in. 188 00:07:48,160 --> 00:07:50,240 Uh and then if we're actually running a 189 00:07:50,240 --> 00:07:52,479 directory with a done domain file or a 190 00:07:52,479 --> 00:07:55,039 zip archive with a done domain file in 191 00:07:55,039 --> 00:07:59,360 those cases it will always add the uh uh 192 00:07:59,360 --> 00:08:02,560 add the target to cy.path regardless of 193 00:08:02,560 --> 00:08:04,400 whether an isolated mode or mod just 194 00:08:04,400 --> 00:08:05,840 because the way those execution models 195 00:08:05,840 --> 00:08:08,479 work. Uh there'll be link at an end 196 00:08:08,479 --> 00:08:10,720 where you can find more details on how 197 00:08:10,720 --> 00:08:14,479 the path initialization works. And 198 00:08:14,479 --> 00:08:16,080 because we're no longer in isolated 199 00:08:16,080 --> 00:08:18,000 mode, 200 00:08:18,000 --> 00:08:22,479 you'll see that if we run in the virtual 201 00:08:22,479 --> 00:08:24,160 environment, 202 00:08:24,160 --> 00:08:26,639 the environment variable has had an 203 00:08:26,639 --> 00:08:29,680 effect. So yeah, so isolated mode turns 204 00:08:29,680 --> 00:08:35,599 that off. So what if we then 205 00:08:35,599 --> 00:08:39,039 drop out of our 206 00:08:39,039 --> 00:08:43,839 drop out of our virtual environment and 207 00:08:43,839 --> 00:08:48,640 but stay in isolated mode. So here 208 00:08:48,640 --> 00:08:50,320 standard library location has stayed the 209 00:08:50,320 --> 00:08:52,880 same and what's different is where we're 210 00:08:52,880 --> 00:08:55,519 looking for installed packages and we're 211 00:08:55,519 --> 00:08:58,000 now looking in the globally installed 212 00:08:58,000 --> 00:09:00,160 system site packages and because this is 213 00:09:00,160 --> 00:09:02,320 Fedora box that's the actual Fedora 214 00:09:02,320 --> 00:09:04,080 packages and we'll be able to see 215 00:09:04,080 --> 00:09:06,800 everything that's come from Fedora. 216 00:09:06,800 --> 00:09:09,519 Um this is actually the original use 217 00:09:09,519 --> 00:09:12,560 case for isolated mode because if you 218 00:09:12,560 --> 00:09:14,399 look at every directory there this is a 219 00:09:14,399 --> 00:09:16,560 root owned Python installation. So CIS 220 00:09:16,560 --> 00:09:18,560 admin installed every single directory 221 00:09:18,560 --> 00:09:19,920 on that list is owned by the system 222 00:09:19,920 --> 00:09:22,320 administrator. So there is no 223 00:09:22,320 --> 00:09:24,800 opportunity for user provided files to 224 00:09:24,800 --> 00:09:26,480 mess with the operation of system 225 00:09:26,480 --> 00:09:28,640 utilities. 226 00:09:28,640 --> 00:09:32,560 And finally 227 00:09:32,560 --> 00:09:35,040 we get our raw unvarnished default 228 00:09:35,040 --> 00:09:37,440 configuration of Python. 229 00:09:37,440 --> 00:09:39,920 This has [snorts] the current working 230 00:09:39,920 --> 00:09:43,440 directory. It has standard library. So 231 00:09:43,440 --> 00:09:46,240 far so good. We have system packages but 232 00:09:46,240 --> 00:09:48,640 then we have user site packages here 233 00:09:48,640 --> 00:09:51,440 which means that lots of opportunities 234 00:09:51,440 --> 00:09:54,320 for user provided code to get loaded. 235 00:09:54,320 --> 00:09:57,279 Um, so yeah. So at that point, who knows 236 00:09:57,279 --> 00:09:58,720 what's installed? Who knows what you're 237 00:09:58,720 --> 00:10:02,279 actually going to be importing? 238 00:10:02,560 --> 00:10:05,959 So let's 239 00:10:08,160 --> 00:10:10,080 So 240 00:10:10,080 --> 00:10:11,519 Python interpreters look in different 241 00:10:11,519 --> 00:10:12,880 places for modules depending on how 242 00:10:12,880 --> 00:10:14,560 they're configured. If we're not writing 243 00:10:14,560 --> 00:10:16,640 Python package installation tools, do we 244 00:10:16,640 --> 00:10:19,839 actually care that much? Well, yeah. As 245 00:10:19,839 --> 00:10:21,680 hinted out a couple of times, having 246 00:10:21,680 --> 00:10:23,279 folders we don't expect on the import 247 00:10:23,279 --> 00:10:25,600 path is a problem. If those folders 248 00:10:25,600 --> 00:10:26,959 contain incompatible versions of the 249 00:10:26,959 --> 00:10:28,640 modules that we're importing and the 250 00:10:28,640 --> 00:10:30,720 path search order means we don't get the 251 00:10:30,720 --> 00:10:33,360 copy that we actually wanted. Uh this is 252 00:10:33,360 --> 00:10:36,160 a process known as module shadowing. So 253 00:10:36,160 --> 00:10:38,320 this talk was born out of an actual work 254 00:10:38,320 --> 00:10:40,560 investigation where we had a production 255 00:10:40,560 --> 00:10:42,720 issue where the mechanism we used to 256 00:10:42,720 --> 00:10:45,040 manage virtual environments on a long 257 00:10:45,040 --> 00:10:48,480 live server was just not working. Um, 258 00:10:48,480 --> 00:10:49,839 and a member of our team figured out 259 00:10:49,839 --> 00:10:53,279 why. Uh, and so while the exact details 260 00:10:53,279 --> 00:10:54,800 of what broke in our case were very 261 00:10:54,800 --> 00:10:56,959 specific to what we were doing or doing 262 00:10:56,959 --> 00:11:00,320 wrong as the case turned out. Um, but 263 00:11:00,320 --> 00:11:02,320 the techniques that we used to identify 264 00:11:02,320 --> 00:11:03,920 the module name shadowing that was the 265 00:11:03,920 --> 00:11:06,000 root cause of our problem. I realized 266 00:11:06,000 --> 00:11:07,839 those were likely to be of general 267 00:11:07,839 --> 00:11:10,880 interest and so this talk was born. 268 00:11:10,880 --> 00:11:12,720 Now of those techniques, one of the 269 00:11:12,720 --> 00:11:14,480 important most important is also one of 270 00:11:14,480 --> 00:11:17,040 the simplest. You just have to remember 271 00:11:17,040 --> 00:11:19,440 that Python keeps track of where 272 00:11:19,440 --> 00:11:22,800 imported modules came from. And so if we 273 00:11:22,800 --> 00:11:25,519 just remember to ask Python where did 274 00:11:25,519 --> 00:11:28,399 that module come from then that can 275 00:11:28,399 --> 00:11:31,120 often just point us directly to that 276 00:11:31,120 --> 00:11:32,800 module that you expected to come from 277 00:11:32,800 --> 00:11:34,399 over here is in fact coming from over 278 00:11:34,399 --> 00:11:36,079 there and is probably not the one you 279 00:11:36,079 --> 00:11:38,160 wanted and is hence the source of your 280 00:11:38,160 --> 00:11:40,240 problems. 281 00:11:40,240 --> 00:11:41,839 So, 282 00:11:41,839 --> 00:11:46,279 let's go back to our 283 00:11:47,519 --> 00:11:50,920 back to here. 284 00:11:51,680 --> 00:11:53,680 And 285 00:11:53,680 --> 00:11:56,399 let's see what we have in this folder. 286 00:11:56,399 --> 00:11:58,959 Oh, hello. We have a not very 287 00:11:58,959 --> 00:12:02,160 interesting file called re.py. 288 00:12:02,160 --> 00:12:04,399 I'm sure that won't cause any problems. 289 00:12:04,399 --> 00:12:07,680 It'll be fine. Hang on. Inspect module 290 00:12:07,680 --> 00:12:10,399 has this nice handy utility 291 00:12:10,399 --> 00:12:14,399 that lets us say inspect 292 00:12:14,399 --> 00:12:18,720 tell me about the re module please. 293 00:12:18,720 --> 00:12:23,360 Oh oops what's gone wrong there? And so 294 00:12:23,360 --> 00:12:26,000 yes so here we see name shadowing in all 295 00:12:26,000 --> 00:12:29,839 its glory. The inspect module uses the 296 00:12:29,839 --> 00:12:32,880 re module. Fair enough. except it can't 297 00:12:32,880 --> 00:12:34,959 see the re module because I've put this 298 00:12:34,959 --> 00:12:38,160 useless piece of empty code in the way. 299 00:12:38,160 --> 00:12:41,360 Now, this is Python 314. Python 314 is 300 00:12:41,360 --> 00:12:43,279 very helpfully said, "Hey, you've 301 00:12:43,279 --> 00:12:48,480 probably stuffed this up." Um, and so if 302 00:12:48,480 --> 00:12:53,120 you if you're on a newer Python 303 00:12:53,120 --> 00:12:56,893 and go see [snorts] 304 00:13:07,920 --> 00:13:10,959 So oops 305 00:13:10,959 --> 00:13:13,600 to me. 306 00:13:13,600 --> 00:13:17,440 So yeah. So it is gone. You can't import 307 00:13:17,440 --> 00:13:19,760 the name compile from the re module and 308 00:13:19,760 --> 00:13:21,360 it's pointing out hey you're shadowing 309 00:13:21,360 --> 00:13:22,800 the standard library. This probably 310 00:13:22,800 --> 00:13:25,200 isn't what you want. 311 00:13:25,200 --> 00:13:28,320 Uh and then similarly because again this 312 00:13:28,320 --> 00:13:30,399 is a new enough version of Python for 313 00:13:30,399 --> 00:13:33,800 that to work 314 00:13:35,440 --> 00:13:39,480 access it by attribute. 315 00:13:39,920 --> 00:13:44,360 And so even with the Whoops. 316 00:13:47,839 --> 00:13:50,839 import 317 00:13:51,040 --> 00:13:55,040 keywords aren't important are they? 318 00:13:55,040 --> 00:13:56,959 So 319 00:13:56,959 --> 00:13:59,680 even with the lazy attribute lookup uh 320 00:13:59,680 --> 00:14:01,760 outside the dedicated syntax, it still 321 00:14:01,760 --> 00:14:03,680 figures out the attribute error. Now if 322 00:14:03,680 --> 00:14:06,880 we go back to older Python versions, the 323 00:14:06,880 --> 00:14:08,880 import 324 00:14:08,880 --> 00:14:11,519 the import case 325 00:14:11,519 --> 00:14:14,320 is still 326 00:14:14,320 --> 00:14:17,320 useful. 327 00:14:17,600 --> 00:14:20,000 So not quite explicit in the hint, but 328 00:14:20,000 --> 00:14:22,560 it does at least where uh say where it 329 00:14:22,560 --> 00:14:25,600 was trying to import from. Um but if we 330 00:14:25,600 --> 00:14:29,480 do the attribute version, 331 00:14:29,600 --> 00:14:31,360 this is where things can get really 332 00:14:31,360 --> 00:14:34,360 cryptic. 333 00:14:34,639 --> 00:14:37,120 So that's that's you you're at that 334 00:14:37,120 --> 00:14:41,800 point you're just going what's going on? 335 00:14:42,000 --> 00:14:45,000 And 336 00:14:45,040 --> 00:14:46,880 and this these are these are the 337 00:14:46,880 --> 00:14:48,160 friendly versions because these are 338 00:14:48,160 --> 00:14:49,839 getting absolute attribute error. You're 339 00:14:49,839 --> 00:14:51,279 not just getting the wrong version that 340 00:14:51,279 --> 00:14:52,800 is not behaving quite the way you 341 00:14:52,800 --> 00:14:57,519 expected. Um but what we can do in older 342 00:14:57,519 --> 00:14:59,680 Python versions 343 00:14:59,680 --> 00:15:02,655 is [snorts] 344 00:15:03,760 --> 00:15:07,440 the import system actually keeps track 345 00:15:07,440 --> 00:15:11,839 of where it loaded modules from. Uh, and 346 00:15:11,839 --> 00:15:15,760 so in the actually let's do a let's do a 347 00:15:15,760 --> 00:15:19,480 nicer version of that. 348 00:15:22,399 --> 00:15:26,079 So yeah, it's the case of even in older 349 00:15:26,079 --> 00:15:28,240 versions if you actually look at the 350 00:15:28,240 --> 00:15:29,839 module spec that is loaded into the 351 00:15:29,839 --> 00:15:32,000 module that will often that will tell 352 00:15:32,000 --> 00:15:34,399 you exactly where it came from and that 353 00:15:34,399 --> 00:15:37,680 is often sufficient to pinpoint the 354 00:15:37,680 --> 00:15:40,000 source of your problems. And this was 355 00:15:40,000 --> 00:15:41,519 actually as far as we had to go in our 356 00:15:41,519 --> 00:15:42,959 investigation. Once we started doing 357 00:15:42,959 --> 00:15:44,480 this, it became obvious things were not 358 00:15:44,480 --> 00:15:46,959 being imported from the right place. And 359 00:15:46,959 --> 00:15:49,759 once we cleaned up the noise, we solved 360 00:15:49,759 --> 00:15:51,680 our problem. 361 00:15:51,680 --> 00:15:53,759 So now, one of the interesting things 362 00:15:53,759 --> 00:15:56,000 about this problem is that this is not 363 00:15:56,000 --> 00:15:57,120 one of the problems that virtual 364 00:15:57,120 --> 00:16:00,079 environments will fix for you. 365 00:16:00,079 --> 00:16:03,079 So 366 00:16:06,160 --> 00:16:08,720 come back here. 367 00:16:08,720 --> 00:16:13,240 We go into our virtual environment. 368 00:16:19,839 --> 00:16:21,759 And yeah, so virtual environment doesn't 369 00:16:21,759 --> 00:16:23,199 help because we're not in isolated mode. 370 00:16:23,199 --> 00:16:24,480 So the current working directory is 371 00:16:24,480 --> 00:16:27,120 still on the path. Uh if we do go into 372 00:16:27,120 --> 00:16:30,680 isolated mode 373 00:16:34,240 --> 00:16:39,440 then our re module works properly and we 374 00:16:39,440 --> 00:16:42,600 can do 375 00:16:49,920 --> 00:16:52,720 and 376 00:16:52,720 --> 00:16:55,279 that point the inspect module will do 377 00:16:55,279 --> 00:16:59,360 its job uh and tell us everything there 378 00:16:59,360 --> 00:17:01,839 is to know about that module. Um so in 379 00:17:01,839 --> 00:17:04,640 versions prior to 315 380 00:17:04,640 --> 00:17:08,000 uh if you if you don't have this 381 00:17:08,000 --> 00:17:09,600 standard library corruption problem, you 382 00:17:09,600 --> 00:17:11,120 just have regular vanilla import 383 00:17:11,120 --> 00:17:13,439 problems, uh inspect module can be very 384 00:17:13,439 --> 00:17:16,480 helpful. Um but yes, your standard 385 00:17:16,480 --> 00:17:18,240 library does need to be working properly 386 00:17:18,240 --> 00:17:22,000 or inspect will not be happy. Um, 387 00:17:22,000 --> 00:17:23,839 and 388 00:17:23,839 --> 00:17:25,679 315 389 00:17:25,679 --> 00:17:28,240 the inspect CLI is pretty robust and 390 00:17:28,240 --> 00:17:30,320 will deal with various things around 391 00:17:30,320 --> 00:17:32,720 name aliasing and so forth correctly. 392 00:17:32,720 --> 00:17:36,400 Um, versions prior to 315. 393 00:17:36,400 --> 00:17:37,840 If you give it a module that actually 394 00:17:37,840 --> 00:17:40,000 exists and is a genuine source module, 395 00:17:40,000 --> 00:17:42,320 it'll all work. If you give it other 396 00:17:42,320 --> 00:17:44,559 things, you get to keep all the shiny 397 00:17:44,559 --> 00:17:48,320 pieces. Um, but yes, does it count as 398 00:17:48,320 --> 00:17:49,760 conference proof in development? if I 399 00:17:49,760 --> 00:17:50,880 was going to talk about this more in 400 00:17:50,880 --> 00:17:54,400 this talk and then found it didn't work. 401 00:17:54,400 --> 00:17:59,280 Um, okay. So, honestly, most important 402 00:17:59,280 --> 00:18:01,280 problems, those two things will actually 403 00:18:01,280 --> 00:18:03,360 get you most of the way there. Uh, 404 00:18:03,360 --> 00:18:08,480 Python-Mite and look at the 405 00:18:08,480 --> 00:18:11,280 uh look at what's going on with your 406 00:18:11,280 --> 00:18:14,679 actual imports. 407 00:18:14,880 --> 00:18:17,880 So 408 00:18:18,799 --> 00:18:21,919 so far we've been discussing relatively 409 00:18:21,919 --> 00:18:23,600 straightforward cases. Python 410 00:18:23,600 --> 00:18:25,280 interpreter is fully responsible for 411 00:18:25,280 --> 00:18:27,919 converting this path. Runtime name 412 00:18:27,919 --> 00:18:30,720 shadowing is reflected on disk. Nothing 413 00:18:30,720 --> 00:18:34,160 too exotic is going on. However, another 414 00:18:34,160 --> 00:18:35,600 potential source of variability is 415 00:18:35,600 --> 00:18:37,360 import time side effects. And for that 416 00:18:37,360 --> 00:18:38,880 it could be useful to know which other 417 00:18:38,880 --> 00:18:40,320 modules are imported before the problem 418 00:18:40,320 --> 00:18:42,240 occurs. We could write a custom 419 00:18:42,240 --> 00:18:43,840 diagnostic script for that, but we don't 420 00:18:43,840 --> 00:18:45,679 need to as the import system provides a 421 00:18:45,679 --> 00:18:47,280 relevant diagnostic feature where 422 00:18:47,280 --> 00:18:49,039 CPython has an implementation dependent 423 00:18:49,039 --> 00:18:51,919 CLI option that reports the individual 424 00:18:51,919 --> 00:18:54,720 and commutive durations for all module 425 00:18:54,720 --> 00:18:57,360 imports. This feature is also a useful 426 00:18:57,360 --> 00:18:58,880 way to check what modules are being 427 00:18:58,880 --> 00:19:00,799 implicitly imported at interpreter 428 00:19:00,799 --> 00:19:02,640 startup. 429 00:19:02,640 --> 00:19:07,000 And I'm only going to 430 00:19:17,919 --> 00:19:21,760 import time is the option 431 00:19:21,760 --> 00:19:24,000 and the -x is basically that this is 432 00:19:24,000 --> 00:19:26,400 technically a CPython specific thing. 433 00:19:26,400 --> 00:19:28,240 Other interpreters may or may not offer 434 00:19:28,240 --> 00:19:30,640 the same feature. 435 00:19:30,640 --> 00:19:32,240 Um, 436 00:19:32,240 --> 00:19:34,799 so you can see there that's everything 437 00:19:34,799 --> 00:19:37,919 that a do nothing Python command will 438 00:19:37,919 --> 00:19:41,520 import uh as of Python 314. 439 00:19:41,520 --> 00:19:43,440 Um, 440 00:19:43,440 --> 00:19:44,960 the 441 00:19:44,960 --> 00:19:46,720 note the site customize and use 442 00:19:46,720 --> 00:19:48,400 customize at the end there. We'll come 443 00:19:48,400 --> 00:19:50,240 back to those. 444 00:19:50,240 --> 00:19:55,559 Um, if we go into isolated mode, 445 00:19:56,799 --> 00:19:59,520 you can see 446 00:19:59,520 --> 00:20:01,440 you site customizer still there. User 447 00:20:01,440 --> 00:20:03,840 customiz is gone. 448 00:20:03,840 --> 00:20:07,360 And if we go into our virtual 449 00:20:07,360 --> 00:20:10,360 environment, 450 00:20:11,200 --> 00:20:13,120 oh, hello. That's that's some that's 451 00:20:13,120 --> 00:20:16,080 done something different. Um so what's 452 00:20:16,080 --> 00:20:19,919 going on there is the specific way uh UV 453 00:20:19,919 --> 00:20:21,520 sets up it virtual environments installs 454 00:20:21,520 --> 00:20:24,000 a path hook uh which is that done to 455 00:20:24,000 --> 00:20:26,000 virtual uh underscore virtual env at the 456 00:20:26,000 --> 00:20:27,840 bottom there which has imported an extra 457 00:20:27,840 --> 00:20:29,360 encoding 458 00:20:29,360 --> 00:20:30,799 uh which is where a lot of those extra 459 00:20:30,799 --> 00:20:32,640 imports come from we'll come back to 460 00:20:32,640 --> 00:20:35,280 that more later now if you've had to 461 00:20:35,280 --> 00:20:37,440 resort to this step I don't actually 462 00:20:37,440 --> 00:20:39,840 have generic debugging advice for you 463 00:20:39,840 --> 00:20:41,360 because 464 00:20:41,360 --> 00:20:42,400 once you're to the point of 465 00:20:42,400 --> 00:20:46,480 investigating module side effects. 466 00:20:46,480 --> 00:20:49,280 It's arbitrary code with arbitrary 467 00:20:49,280 --> 00:20:50,799 consequences. 468 00:20:50,799 --> 00:20:54,159 Um so yeah, mostly what you're looking 469 00:20:54,159 --> 00:20:58,960 for here is that difference between the 470 00:20:58,960 --> 00:21:02,559 clean environment with uh what gets 471 00:21:02,559 --> 00:21:06,720 imported by default uh and things like 472 00:21:06,720 --> 00:21:08,960 that that those import time side 473 00:21:08,960 --> 00:21:11,440 effects. Uh the other thing that can get 474 00:21:11,440 --> 00:21:13,520 interesting is if you do more in your 475 00:21:13,520 --> 00:21:17,840 sample command than a pass option that 476 00:21:17,840 --> 00:21:22,000 uh that doesn't do anything interesting. 477 00:21:22,000 --> 00:21:23,840 Uh 478 00:21:23,840 --> 00:21:26,840 so 479 00:21:29,440 --> 00:21:31,760 now what if looking at all of those 480 00:21:31,760 --> 00:21:32,960 things still hasn't let us work out 481 00:21:32,960 --> 00:21:35,120 what's going on? What if we want to know 482 00:21:35,120 --> 00:21:38,400 more? Do you know CPython itself has 483 00:21:38,400 --> 00:21:42,159 variable has verbosity levels? 484 00:21:42,159 --> 00:21:43,840 So 485 00:21:43,840 --> 00:21:45,679 it does you can turn on additional 486 00:21:45,679 --> 00:21:47,600 diagnostic outputs for the import 487 00:21:47,600 --> 00:21:49,600 system. So the first tier of diagnostics 488 00:21:49,600 --> 00:21:51,919 provide details of the outcome of import 489 00:21:51,919 --> 00:21:54,640 attempts and the second tier includes a 490 00:21:54,640 --> 00:21:56,080 lot more information on what imports 491 00:21:56,080 --> 00:21:59,360 it's trying uh as it goes through. Now, 492 00:21:59,360 --> 00:22:00,720 if you're having to resort to this 493 00:22:00,720 --> 00:22:01,840 option, you're either hunting down 494 00:22:01,840 --> 00:22:04,080 particularly messy environment issues or 495 00:22:04,080 --> 00:22:05,679 you're working on modifying the 496 00:22:05,679 --> 00:22:07,600 important system itself and the change 497 00:22:07,600 --> 00:22:10,559 isn't going to plan. Either way, I'm 498 00:22:10,559 --> 00:22:12,559 sorry, you're probably having a very bad 499 00:22:12,559 --> 00:22:16,480 day. Um, so the output is incredibly 500 00:22:16,480 --> 00:22:18,080 spammy, so you likely need to filter it 501 00:22:18,080 --> 00:22:20,480 programmatically rather than by I. 502 00:22:20,480 --> 00:22:22,159 That's easier if the offending module 503 00:22:22,159 --> 00:22:24,320 has a more distinctive name than lots of 504 00:22:24,320 --> 00:22:27,039 words have in them. uh if you require 505 00:22:27,039 --> 00:22:29,039 word boundaries either side of the name 506 00:22:29,039 --> 00:22:31,200 that actually cleans up most of the 507 00:22:31,200 --> 00:22:34,240 output. Now 508 00:22:34,240 --> 00:22:39,039 I'm going to very quickly 509 00:22:39,039 --> 00:22:44,120 I'm not going to do this by hand. 510 00:22:58,320 --> 00:23:01,640 did it again. 511 00:23:03,600 --> 00:23:06,960 So yes, that's you can basically see 512 00:23:06,960 --> 00:23:09,440 checking a bunch of directories failing 513 00:23:09,440 --> 00:23:11,200 uh eventually finding it in the working 514 00:23:11,200 --> 00:23:15,600 directory uh and then going oh okay 515 00:23:15,600 --> 00:23:17,600 that's where it's done it. If we go into 516 00:23:17,600 --> 00:23:20,320 isolated mode 517 00:23:20,320 --> 00:23:22,000 we can see it actually finds the real 518 00:23:22,000 --> 00:23:23,520 thing. 519 00:23:23,520 --> 00:23:25,360 uh which is the actual re module and 520 00:23:25,360 --> 00:23:27,600 then does a bunch of other stuff of re 521 00:23:27,600 --> 00:23:29,679 subm module imports. 522 00:23:29,679 --> 00:23:34,760 Um and if we do a 523 00:23:40,320 --> 00:23:42,559 module that doesn't exist that we search 524 00:23:42,559 --> 00:23:45,039 the entire 525 00:23:45,039 --> 00:23:48,360 path for. 526 00:23:49,200 --> 00:23:51,919 Then you can see a lot more a lot more 527 00:23:51,919 --> 00:23:54,480 things that it's looking for. 528 00:23:54,480 --> 00:23:57,360 Uh 529 00:23:57,360 --> 00:24:01,159 wait, what's that done? 530 00:24:01,440 --> 00:24:03,760 Yeah. 531 00:24:03,760 --> 00:24:05,520 Um, 532 00:24:05,520 --> 00:24:13,320 so and then if you just do an example of 533 00:24:14,640 --> 00:24:17,640 the 534 00:24:20,400 --> 00:24:22,400 Yeah, that would be why I say there's 535 00:24:22,400 --> 00:24:25,520 programmatic filtering required. 536 00:24:25,520 --> 00:24:29,440 Just a just a little bit of noise. Um, 537 00:24:29,440 --> 00:24:32,440 okay. 538 00:24:41,120 --> 00:24:44,120 So, 539 00:24:44,799 --> 00:24:46,880 I'm not going to do demos for these um 540 00:24:46,880 --> 00:24:48,880 because I'm running out of time, but 541 00:24:48,880 --> 00:24:52,400 that's why the these are some of the 542 00:24:52,400 --> 00:24:54,080 more exotic potential problems you can 543 00:24:54,080 --> 00:24:56,240 run into. So, if you've got site if site 544 00:24:56,240 --> 00:24:58,080 customizer, user customizer populated, 545 00:24:58,080 --> 00:24:59,679 so the import system imports those 546 00:24:59,679 --> 00:25:02,000 automatically. um or the interpreter 547 00:25:02,000 --> 00:25:03,520 imports those automatically on startup. 548 00:25:03,520 --> 00:25:06,720 They do have legitimate use cases. Um so 549 00:25:06,720 --> 00:25:09,919 VM stacks uh which is a library for or 550 00:25:09,919 --> 00:25:11,679 tool for stacking virtual environments 551 00:25:11,679 --> 00:25:13,679 on top of each other uses customiz site 552 00:25:13,679 --> 00:25:17,279 customized to make that work. Um 553 00:25:17,279 --> 00:25:19,360 so it's one form of startup code. Uh and 554 00:25:19,360 --> 00:25:23,520 then PTH files and starting from 315 555 00:25:23,520 --> 00:25:27,120 start files uh in installed modules uh 556 00:25:27,120 --> 00:25:29,279 can run things at startup. So that 557 00:25:29,279 --> 00:25:32,240 virtual end that we saw earlier uh is 558 00:25:32,240 --> 00:25:36,000 actually a path file that uh UV installs 559 00:25:36,000 --> 00:25:37,360 into the virtual environments that it 560 00:25:37,360 --> 00:25:39,600 creates. Uh and that has side effects on 561 00:25:39,600 --> 00:25:41,200 startup. 562 00:25:41,200 --> 00:25:45,600 Uh and so yeah, so if you you can um one 563 00:25:45,600 --> 00:25:48,320 of the things you can extract from the 564 00:25:48,320 --> 00:25:51,760 verbose start uh Python output is those 565 00:25:51,760 --> 00:25:54,400 startup files being processed. 566 00:25:54,400 --> 00:25:57,600 Um, and then yeah, the techniques in 567 00:25:57,600 --> 00:26:00,400 this talk are aimed at debugging the 568 00:26:00,400 --> 00:26:02,400 default configuration of Python's import 569 00:26:02,400 --> 00:26:04,720 system. So, built-in imports, frozen 570 00:26:04,720 --> 00:26:08,159 imports, path imports, uh, and then zip 571 00:26:08,159 --> 00:26:10,000 and file system imports configured in 572 00:26:10,000 --> 00:26:14,159 the path hooks. Um, 573 00:26:14,159 --> 00:26:15,679 those 574 00:26:15,679 --> 00:26:17,919 that's just how Python imports work 575 00:26:17,919 --> 00:26:20,960 normally. That's all customizable. Uh, 576 00:26:20,960 --> 00:26:23,279 and so startup code and input module 577 00:26:23,279 --> 00:26:25,120 input side effects may alter how the 578 00:26:25,120 --> 00:26:27,360 import system itself works. And once 579 00:26:27,360 --> 00:26:30,400 that happens, then you you have a whole 580 00:26:30,400 --> 00:26:32,159 new host of potential problems to deal 581 00:26:32,159 --> 00:26:34,559 with. Um, this is almost never going to 582 00:26:34,559 --> 00:26:39,039 be your problem, except when it is. 583 00:26:39,039 --> 00:26:42,799 Uh and so the 584 00:26:42,799 --> 00:26:46,080 way to check that whether that is going 585 00:26:46,080 --> 00:26:48,640 on uh is to poke around in the CIS 586 00:26:48,640 --> 00:26:50,960 variables that control that aspect of 587 00:26:50,960 --> 00:26:55,600 the input system. Uh and yes that's 588 00:26:55,600 --> 00:26:57,600 that's the thing. Uh the other way 589 00:26:57,600 --> 00:26:59,200 people get themselves into trouble is 590 00:26:59,200 --> 00:27:03,200 with hot reloading. Uh which is 591 00:27:03,200 --> 00:27:04,880 a useful feature for things like web 592 00:27:04,880 --> 00:27:08,000 server development. Um 593 00:27:08,000 --> 00:27:10,559 there are so many ways that can break uh 594 00:27:10,559 --> 00:27:13,520 that yeah basically if you are hot 595 00:27:13,520 --> 00:27:15,520 reloading a system and it is just being 596 00:27:15,520 --> 00:27:18,480 weird and doing stuff like impossible 597 00:27:18,480 --> 00:27:21,200 exceptions not getting caught or 598 00:27:21,200 --> 00:27:23,919 exceptions that should have been caught. 599 00:27:23,919 --> 00:27:25,120 Yeah, exceptions that should have been 600 00:27:25,120 --> 00:27:27,679 caught not getting caught. Um just try 601 00:27:27,679 --> 00:27:29,679 restarting from scratch and making sure 602 00:27:29,679 --> 00:27:31,440 everything is running the same copy of 603 00:27:31,440 --> 00:27:33,360 all the objects that it uh is supposed 604 00:27:33,360 --> 00:27:38,320 to be having. Um yeah 605 00:27:38,320 --> 00:27:40,080 and so yeah so if you're interested in 606 00:27:40,080 --> 00:27:41,440 exploring the import system more 607 00:27:41,440 --> 00:27:43,120 generally it's a detailed specification 608 00:27:43,120 --> 00:27:45,919 in the language reference that points to 609 00:27:45,919 --> 00:27:50,240 additional resources. Um the CPython CLI 610 00:27:50,240 --> 00:27:52,400 docs provide details of what's enabled 611 00:27:52,400 --> 00:27:54,960 in isolated mode and options for turning 612 00:27:54,960 --> 00:27:56,240 all those settings on and off 613 00:27:56,240 --> 00:27:57,919 individually rather than with the big 614 00:27:57,919 --> 00:28:00,080 isolated mode hammer. 615 00:28:00,080 --> 00:28:03,840 um -m site and -m inspect far from the 616 00:28:03,840 --> 00:28:05,760 only CLIs built into the standard 617 00:28:05,760 --> 00:28:08,480 library. Uh so we do have a full list of 618 00:28:08,480 --> 00:28:10,720 them in the standard library docs 619 00:28:10,720 --> 00:28:13,279 themselves. Uh and then Trey Hunter also 620 00:28:13,279 --> 00:28:16,000 has an excellent overview of them that 621 00:28:16,000 --> 00:28:18,159 categorizes them into different groups 622 00:28:18,159 --> 00:28:20,559 and has explanations of what each one 623 00:28:20,559 --> 00:28:21,919 does. 624 00:28:21,919 --> 00:28:26,159 Um, and then yeah, there's also a link 625 00:28:26,159 --> 00:28:28,640 there to an article about 626 00:28:28,640 --> 00:28:30,799 using virtual environments in Linux 627 00:28:30,799 --> 00:28:32,720 containers, uh, which I think is one of 628 00:28:32,720 --> 00:28:34,960 the best explanations of using VMs to 629 00:28:34,960 --> 00:28:37,200 make runtime behavior easier to re 630 00:28:37,200 --> 00:28:40,640 reason about. Now, I'm pretty sure I've 631 00:28:40,640 --> 00:28:42,240 run too long to allow time for 632 00:28:42,240 --> 00:28:43,979 questions. 633 00:28:43,979 --> 00:28:45,679 [laughter] 634 00:28:45,679 --> 00:28:48,640 Uh, but I will be around all week so or 635 00:28:48,640 --> 00:28:51,600 all weekend. So happy to chat about 636 00:28:51,600 --> 00:28:54,000 CPython in general and for the first 637 00:28:54,000 --> 00:28:55,679 time in years we actually have a CPython 638 00:28:55,679 --> 00:28:59,279 and sprint this sprints this year. So 639 00:28:59,279 --> 00:29:02,975 yes, thank you. Okay, thank you. 640 00:29:02,975 --> 00:29:04,995 [applause] 641 00:29:07,520 --> 00:29:09,440 Thank you Alyssa. And for being a 642 00:29:09,440 --> 00:29:12,320 speaker on Pyon AU 2026, we'd like to 643 00:29:12,320 --> 00:29:14,799 present you with our speaker gift. And a 644 00:29:14,799 --> 00:29:16,960 round of applause for Alyssa and see her 645 00:29:16,960 --> 00:29:20,715 again in the hallway track. [applause]