PyWart: "Python's import statement and the history of external dependencies"

Ian Kelly ian.g.kelly at gmail.com
Fri Nov 21 16:33:53 CET 2014


On Thu, Nov 20, 2014 at 8:53 PM, Rick Johnson
<rantingrickjohnson at gmail.com> wrote:
> FOR INSTANCE: Let's say i write a module that presents a
> reusable GUI calendar widget, and then i name the module
> "calender.py".
>
> Then Later, when i try to import *MY* GUI widget named
> "calendar", i will not get *MY* calendar widget, no, i will
> get the Python calendar module.

Because like a fool you created a local module with a totally generic
name like "calendar" and dumped it into the top-level namespace. The
Python import system gives you the ability to create packages, so use
them -- create a package to contain all the widgets you create. If
they're only for your own use, then you can just call it ricklib or
anything else you want.  Then your import becomes:

import ricklib.calendar  # or from ricklib import calendar

Now you can drop as much stuff in there as you like, and none of it
will ever conflict with the standard library (unless a standard
"ricklib" module is added, which is unlikely).

> The reason Python finds the library module instead of my
> module is because the Python library is higher in search
> path than my module.

Your PYTHONPATH is added to the sys.path before the Python library,
not after, so to the extent that there is an issue, it's actually the
other way around. You would get your local calendar module when trying
to import the system calendar module.

> # Contrary to popular belief, sys.path is *NOT* a module,  #
> # no, it's a global!                                       #

I really doubt that this is a popular belief.

> This is another confusing fundamental of Python, it seems *MORE*
> intuitive that changes to the "import search path" would only
> affect the *CURRENT* module's "import search path", but that's
> is not the case!

This just seems like it would create a maintenance nightmare. Before
you could import anything, you'd have to figure out what the search
path is for the particular module you're working and whether it
happens to include the particular package you want. You find it
doesn't, so you make a local change to the search path. Later, you
make the same change to other modules that need to import it. Later
still, the package moves to a different location in the file system,
and now you get to go through and update every one of those modules
with the new directory. Lucky you.

And after all that, it would still fail if you happened to want to
import both "calendar" modules into the same module.

> in the 25% of cases where *NAME SHADOWING* or where the
> author knows the location and can specify the location to
> save "lobby boy" from knocking on doors until his knuckles
> bleed, the author should have an option defining the search
> path *LOCALLY* (in a manner that will *NOT* affect the
> "import search path" further down the import chain), WITHOUT
> needing to import one of the many discombobulated and
> confusing import tools that Python has tortured this
> community with.

By doing so, the author would also make the module non-portable. This
is a major problem if they intend to distribute it, but still a
problem even if they don't. Any time the code is moved to a new system
and placed in a new location (or worse: moved to a new operating
system) the code will have to be updated. And you can pretty much
forget about hosting it on a network share.

>> 3) Filepath imports (deprecated in 3.4 but under discussion for
>> reprecation or replacement)
>>
>>      import importlib.machinery
>>
>>      loader = importlib.machinery.SourceFileLoader("module.name",
>>          "/path /to/file.py")
>>      foo = loader.load_module()
>>      foo.MyClass()
>
> That's ridiculously noisy. I have an idea, if you *REALLY*
> want to introduce boilerplate hell then Python should adopt
> "import header files", NOT!

It's three lines of code to replace one. Two if you exclude the
importlib.machinery import that doesn't need to be repeated.  Is this
really any worse than something like:

local_search_path.insert(0, "/path/to/local/module")
import my_local_module

that you are proposing?



More information about the Python-list mailing list