I am trying to build a python wheel on a complex program, and I have issues with imports. So I managed to reproduce it on a elementary example. The program works fine when directly called, but does not works when trying to import it from an installed wheel.
Here is my example structure :
wheel_test
|-setup.py
|-toto
|-__init__.py
|-main.py
|-tata.py
|-subfolder
|-__init__.py
|-titi.py
main.py
# coding: utf8
from tata import tata
import subfolder.titi as titi
def test_fct():
t1 = tata()
print(f't1 number = {t1.random_number}')
print(f'Is t1 number even: {titi.is_even(t1.random_number)}')
test_fct()
(Here t1
is an instance of class tata
, which just store a random number in self.random_number
, and the titi.py
file just contains an is_even(number)
function, telling if a number is even or not)
This runs just fine when launched :
> python "some_path\wheel_test\toto\main.py"
t1 number = 11
Is t1 number even: False
But then, I want to make a wheel of this, using a setup file : setup.py
# coding: utf8
import os
from setuptools import find_packages, setup
root = os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))
os.chdir(root)
setup(
name='toto',
packages=find_packages(),
version='0.1',
description='Wheel test',
author='Arkeen',
license='None',
)
(I copied the os.chdir
lines from [this post])
This create a toto-0.1-py3-none-any.whl
file. I then run $ pip install path_to_newly_created_whell/toto-0.1-py3-none-any.whl
, which seems OK.
But when I want to run this code :
# coding: utf8
import toto.main as maintoto
maintoto.test_fct()
I got the following error :
File "some_path\wheel_test\toto\main.py", line 2, in <module>
from tata import tata
ModuleNotFoundError: No module named 'tata'
So why this outcome ? Why does this code runs fine with python but not as a wheel ?
Edit : Thanks @Countour-Integral for pointing me the right direction. Still, I had to go deeper into Python modules
, packages
, relative and absolute import
to fully understand this. So, to anyone here having a similar issue, I would recommend to read this :
You are getting a ModuleNotFoundError
because the interpreter is searching for a global module named tata
, and not looking in the current directory. You are also repeating this behavior, in your first code block.
In the following snippet you are running main.py
as python path/to/main.py
import subfolder.titi as titi # Does not throw any error
the reason this does not throw any error is because, you are not running main
as a package, so when you reference subfolder
it checks in your current working directory.
Instead when you try to run setup.py
to build, the interpreter will run everything as a package, and thus, will not look in any local directories. You'll have to change your imports like this
# notice the .
from .subfolder import titi
from .tata import tata
Your file structure looks something like this
-> module (directory)
---- main.py
---- tata.py
----> subfolder (directory)
-------- titi.py
to run any of these as a module, instead of using python main.py
you'll have to cd 1 step back, into the parent directory of module
and use python -m module main.py
,and make sure that you are using imports with . to refrence files in the same directory. Normally this is how development of python-pip packages is done, in order to make it easier in the setup.py
proccess.