Skip to content
Advertisement

Attempted relative import beyond toplevel package

Here is my folder structure:

JavaScript

In test_bash__init__.py I have:

JavaScript

while in test_bsa_files.py:

JavaScript

Now when I issue:

JavaScript

I get:

JavaScript

Since ‘Mopy” is in the sys.path and bosh__init__.py is correctly resolved why it complains about relative import above the top level package ? Which is the top level package ?

Incidentally this is my attempt to add tests to a legacy project – had asked in Python test package layout but was closed as a duplicate of Where do the Python unit tests go?. Comments on my current test package layout are much appreciated !


Well the answer below does not work in my case:

The module bash.py is the entry point to the application containing:

JavaScript

When I use import bash.bosh or from bash import bosh I get:

JavaScript

This usage message is from the main() in bash.

Advertisement

Answer

TLDR: Do

JavaScript

or

JavaScript

Avoid modifying sys.path, as this duplicates modules.


When you do

JavaScript

it will import the module bosh. This means Mopy/bash is in your sys.path, python finds the file bosh there, and imports it. The module is now globally known by the name bosh. Whether bosh is itself a module or package doesn’t matter for this, it only changes whether bosh.py or bosh/__init__.py is used.

Now, when bosh tries to do

JavaScript

this is not a file system operation (“one directory up, file bass”) but a module name operation. It means “one package level up, module bass”. bosh wasn’t imported from its package, but on its own, though. So going up one package is not possible – you end up at the package '', which is not valid.

Let’s look at what happens when you do

JavaScript

instead. First, the package bash is imported. Then, bosh is imported as a module of that package – it is globally know as bash.bosh, even if you used from bash import bosh.

When bosh does

JavaScript

that one works now: going one level up from bash.bosh gets you to bash. From there, bass is imported as bash.bass.

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