Reputation: 1438
My folder/file structrue is:
testpkg/test/__init__.py;
testpkg/test/test1.py
testpkg/test/test2.py
testpkg/setup.py
testpkg/test/__init__.py
file is empty.
testpkg/test/test1.py
file content:
class Test1:
def __init__(self, name):
self.name = name
def what_is_your_name(self):
print(f'My name is {self.name}')
testpkg/test/test2.py
file content:
from .test1 import Test1
def main():
t = Test1('me')
t.what_is_your_name()
if __name__ == '__main__':
main()
/testpkg/setup.py
content:
from setuptools import setup
setup(name='test',
version='0.1',
packages=['test'],
entry_points={
'console_scripts': [
'test_exec = test.test2:main'
]
}
)
I can't debug/run test2.py
script directly because it gives me error:
» python test/test2.py
Traceback (most recent call last):
File "test/test2.py", line 1, in <module>
from .test1 import Test1
ModuleNotFoundError: No module named '__main__.test1'; '__main__' is not a package
But when i install it with pip install -U .
it works:
» pip install -U .
Processing /home/kossak/Kossak/files_common/PythonProjects/testpkg
Installing collected packages: test
Found existing installation: test 0.1
Uninstalling test-0.1:
Successfully uninstalled test-0.1
Running setup.py install for test ... done
Successfully installed test-0.1
» test_exec
My name is me
The question is: How to write test2.py
properly so it works in both ways - directly (so I can debug it in PyCharm or just run with python test2.py
) and after installing the test
package? I tried changing the line:
from .test1 import Test1
to
from test1 import Test1
(removed dot)
and I can run test2.py
from command line, but then after installing, my script "test_exec" gives me error:
Traceback (most recent call last):
File "/home/kossak/anaconda3/bin/test_exec", line 11, in <module>
load_entry_point('test==0.1', 'console_scripts', 'test_exec')()
File "/home/kossak/anaconda3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg/pkg_resources/__init__.py", line 565, in load_entry_point
File "/home/kossak/anaconda3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg/pkg_resources/__init__.py", line 2598, in load_entry_point
File "/home/kossak/anaconda3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg/pkg_resources/__init__.py", line 2258, in load
File "/home/kossak/anaconda3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg/pkg_resources/__init__.py", line 2264, in resolve
File "/home/kossak/anaconda3/lib/python3.6/site-packages/test/test2.py", line 1, in <module>
from test1 import Test1
ModuleNotFoundError: No module named 'test1'
Upvotes: 4
Views: 6554
Reputation: 11410
Basically, you are getting trapped in python's relative import gotcha. Python import system is bit complicated, when it comes to relative imports. So, relative imports have to be used with caution(For that, try to give such names to your module, which doesn't collides with standard modules/packages). You'll always face this problem, when you write any file in the python package. You'll have two scenarios :-
1) Running file as module
python -m package.module
2) Runnning file as script
# cd package
python module.py
In normal scenarios, things will be fine, but when you do relative imports like what you have done,then running file as script, will cause problem as relative imports are resolved against __name__
module variable, which will be '__main__'
in case of script and, thus, it'll face issue in resolving relative imports.
Refer to following article :- http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html
Upvotes: 0