Kossak
Kossak

Reputation: 1438

Import Another File Error

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

Answers (2)

Mangu Singh Rajpurohit
Mangu Singh Rajpurohit

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

Robert Valencia
Robert Valencia

Reputation: 1752

Try importing it like this: from test.test1 import Test1

Upvotes: 2

Related Questions