Skip to content
Advertisement

Relative imports in Python 3

I want to import a function from another file in the same directory.

Usually, one of the following works:

JavaScript
JavaScript

…but the other one gives me one of these errors:

JavaScript
JavaScript
JavaScript

Why is this?

Advertisement

Answer

unfortunately, this module needs to be inside the package, and it also needs to be runnable as a script, sometimes. Any idea how I could achieve that?

It’s quite common to have a layout like this…

JavaScript

…with a mymodule.py like this…

JavaScript

…a myothermodule.py like this…

JavaScript

…and a main.py like this…

JavaScript

…which works fine when you run main.py or mypackage/mymodule.py, but fails with mypackage/myothermodule.py, due to the relative import…

JavaScript

The way you’re supposed to run it is…

JavaScript

…but it’s somewhat verbose, and doesn’t mix well with a shebang line like #!/usr/bin/env python3.

The simplest fix for this case, assuming the name mymodule is globally unique, would be to avoid using relative imports, and just use…

JavaScript

…although, if it’s not unique, or your package structure is more complex, you’ll need to include the directory containing your package directory in PYTHONPATH, and do it like this…

JavaScript

…or if you want it to work “out of the box”, you can frob the PYTHONPATH in code first with this…

JavaScript

It’s kind of a pain, but there’s a clue as to why in an email written by a certain Guido van Rossum…

I’m -1 on this and on any other proposed twiddlings of the __main__ machinery. The only use case seems to be running scripts that happen to be living inside a module’s directory, which I’ve always seen as an antipattern. To make me change my mind you’d have to convince me that it isn’t.

Whether running scripts inside a package is an antipattern or not is subjective, but personally I find it really useful in a package I have which contains some custom wxPython widgets, so I can run the script for any of the source files to display a wx.Frame containing only that widget for testing purposes.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement