Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

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.