Exploring Tips and Tricks
00:00 In the previous lesson, I showed you how you can run scripts inside a zip file. In this lesson, I’ll show you some quick tips and tricks when dealing with imports.
00:09 Python just keeps adding features. Some features are so important that they also get released as third-party libraries so that older versions of Python can take advantage of them.
00:19 That means that if your program is going to support multiple versions of Python, its imports have to handle the built-in versus third-party situation. There are two ways of handling this.
00:30
For example, the importlib.resources
module that I used in a previous lesson was added to Python in 3.7, but a backport called importlib_
resources
was also released.
00:43
If you’ve got code that predates Python 3.7, the package name is different. It needs the third-party. One way of handling this is to surround the import in a try-except block. If a ModuleNotFoundError
is thrown, you load the third-party module instead.
00:59 Alternatively, you can be explicit about your Python version.
01:04 This code accomplishes the same thing, but instead of checking if the import fails, it checks what version of Python is being run and conditionally imports the appropriate module.
01:14 A quick note while I’m here, older code sometimes treated the version number as a float that fell apart once 3.10 came. Turns out mathematically that 3.10 is smaller than 3.9.
01:27
When checking for version information, you should always use a tuple to do the comparison. (3, 10)
does get sorted as larger than (3, 9)
.
01:37
Backports aren’t the only case. There are also third-party libraries out there that are drop-in replacements for built-in libraries. For example, the ujson
library has been optimized for speed, and if it’s present, you might want to use it instead of the built-in json
.
01:53 There’s one more way to tackle this kind of problem if what you need is just to stub the library out if it’s not there. Python’s testing libraries have a way of mocking objects.
02:04
Normally they’re done for controlling tests like mocking the today()
call on a date object so that it always returns a known value for your test.
02:12
In certain situations, you can use a mock if the supported library isn’t there. One example of this is using coloring in the terminal. Say you were using the colorama
library but wanted to fall back in situations where it hasn’t been installed. By having a mock, your code can still call the things, but it calls the mock instead.
02:31 This way, your program just wouldn’t include the color codes and would gracefully degrade to regular old text.
02:38 You’ve seen several examples in this course where bare code in a module gets run when the module is imported. Since scripts and modules are the same thing, if you want to load a utility function from a script with bare code in it, you’d end up running all the bare code in that script.
02:55
The solution to this problem is to have no bare code. The __name__
attribute contains the name of the current module. When a file gets run as a script, the __name__
value contains the string “__main__”.
03:09
This allows you to check what the module name is at runtime. In script mode, the if
statement gets run, but in module mode it does not.
03:19 Importing can be a bit expensive and it usually happens all upfront for your program. To help you understand the performance costs of your imports, the CPython interpreter has a mode where it will time the importing process.
03:32
You do this with the -X importtime
command-line flag. I’ve used the -c
argument to run code in the string, which in this case is simply importing the math
module, the -X importtime
flag then spits out a report on the performance of the imports in the code.
03:51
Even just those two words, import math
, involves a lot of stuff because Python imports system pieces under the covers.
04:00 I’m only showing a part of the results here, but you can see each of the import calls and its associated timing information.
04:08 PEP 8 makes recommendations about what your imports should look like. They should all be at the top of the file, imports should be on separate lines instead of separated lists.
04:19 I violate this one all the time. These are recommendations, not rules. You should organize your imports into groups. Those groups should start with standard library imports, then third-party ones, and then your local ones.
04:33 Imports should be alphabetical and you should prefer absolute imports over relative ones.
04:39
Also, you should avoid using wildcard imports as they muddy the namespace. There are a variety of code quality tools such as linters out there, which will clean up your imports and make them more compliant with PEP 8. For example, the isort
tool reorders your imports according to these guidelines.
04:58
Here is a compliant example, split up into standard, third-party, and local groups and alphabetical. Note that there are two imports from typing
on the same line.
05:09 This is okay because they’re from the same package. That whole same line commma-separated recommendation is about importing multiple top-level packages on the same line, not this situation.
05:21 Wow. Congrats on making it this far. It’s a lot of course. Last up, I’ll summarize what you’ve learned and point you at other courses and tutorials you might find interesting.
Become a Member to join the conversation.