Slide 1

Slide 1 text

Diving deep on how imports work in Python PyCon Taiwan, 2017 presented by Tasdik Rahman (@tasdikrahman)

Slide 2

Slide 2 text

But Why?

Slide 3

Slide 3 text

Modules

Slide 4

Slide 4 text

Terminology •Loader Loads a module •Finder Finds a module

Slide 5

Slide 5 text

Module search path

Slide 6

Slide 6 text

sys.path

Slide 7

Slide 7 text

>>> import sys >>> >>> pprint(sys.path) ['', '/usr/local/Cellar/python3/3.6.0/Frameworks/ Python.framework/Versions/3.6/lib/python36.zip', '/usr/local/Cellar/python3/3.6.0/Frameworks/ Python.framework/Versions/3.6/lib/python3.6', '/usr/local/Cellar/python3/3.6.0/Frameworks/ Python.framework/Versions/3.6/lib/python3.6/lib- dynload', '/usr/local/lib/python3.6/site-packages'] >>>

Slide 8

Slide 8 text

Compiled Python files

Slide 9

Slide 9 text

• __pycache__ under a name like module.version.pyc • __pycache__/spam.cpython-33.pyc • platform independent • regular lookup with source checking for modification.

Slide 10

Slide 10 text

import foo

Slide 11

Slide 11 text

2 step process • find a module, loading and initialising it if necessary • define a name or names in the local namespace for the scope where the "import" statement occurs.

Slide 12

Slide 12 text

If module is retrieved successfully

Slide 13

Slide 13 text

import foo # foo imported and bound locally import foo.bar.baz 
 # foo.bar.baz imported, foo bound locally import foo.bar.baz as fbb 
 # foo.bar.baz imported and bound as fbb

Slide 14

Slide 14 text

from foo.bar import baz

Slide 15

Slide 15 text

• find the module specified in the "from" clause, loading and initialising if necessary • for each of the identifiers specified in the "import" clauses: 1. check if the imported module has an attribute by that name 2. attempt to import a submodule with that name and check the imported module again for that attribute 3. if the attribute is not found, "ImportError" is raised.

Slide 16

Slide 16 text

from foo.bar import baz # foo.bar.baz imported and bound as baz from foo import attr # foo imported and foo.attr bound as attr

Slide 17

Slide 17 text

from foo import *

Slide 18

Slide 18 text

Packages

Slide 19

Slide 19 text

Advantages?

Slide 20

Slide 20 text

car/ Top-level package __init__.py Initialize the car package engine/ Subpackage for engine behaviour __init__.py rev.py temperature.py fuel.py coolant.py ... transmission/ Subpackage for transmission __init__.py forward.py reverse.py ... infotainment/ Subpackage for infotainment system __init__.py music.py reverseparking.py chilledbeer.py ...

Slide 21

Slide 21 text

__init__.py

Slide 22

Slide 22 text

import car.engine.rev car.engine.rev.spin(…) # OR from car.engine import rev rev.spin(...) # OR from car.engine.rev import spin spin(...)

Slide 23

Slide 23 text

__all__

Slide 24

Slide 24 text

from car.engine import * # car/engine/__init__.py __all__ = ["temperature", "fuel", "coolant"]

Slide 25

Slide 25 text

What if there is no __all__ ?

Slide 26

Slide 26 text

Intra-package reference

Slide 27

Slide 27 text

# car/engine/temperature from car.transmission import forward from . import forward from .. import transmission from ..infotainment import music

Slide 28

Slide 28 text

Some takeaways

Slide 29

Slide 29 text

Questions?
 
 Would be happy to take them :) http://tasdikrahman.me/
 @tasdikrahman