Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python3 - how to correctly do absolute imports and make Pylint happy

I am having a huge trouble trying to understand Python 3 imports (I'm using Python 3.5). This seems to be a million-dollar question and I know it has been answered everywhere. However I don't manage to really get a good understanding of how things are supposed to be done; answers on the Internet vary a lot. So sorry in advance if this is a nearly duplicate answer. I would really appreciate references to good reading material.

So I have the following dummy project:

/my_project/main.py
/my_project/lib/__init__.py
/my project/lib/my_lib.py

If possible, I would like to:

  • Be able to run my program as python3 main.py, having my_project as current working directory.
  • Not modify the PYTHONPATH at any time.
  • Make pylint happy.
  • Use correct Python3 imports.

main.py contains:

from .lib.my_lib import foo

if __name__ == '__main__':
    foo()

And foo is accordingly defined in lib/my_lib.py

With that configuration, I get:

SystemError: Parent module '' not loaded, cannot perform relative import

I can get around the error by importing like:

from lib.my_lib import foo

But then 1) this is not a Python3 absolute import, right? 2) Pylint complains: Unable to import 'lib.my_lib' (import-error)

The next thing I tried is to add a my_project/__init__.py, and import like this:

from my_project.lib.my_lib import foo

In this case pylint is happy but then I cannot run as: python3 main.py: ImportError: No module named 'my_project'

Then the only way I can run it is from the parent directory as a module: python3 -m my_project.main.

So my question is: is it possible at all to do the imports in a correct way, while still being able to execute it as python3 main.py?

Thanks a lot!

like image 648
user1011113 Avatar asked Dec 22 '17 10:12

user1011113


1 Answers

I would do something like:

/path/README
/path/requirements.txt
/path/cleverappname/__main__.py
/path/cleverappname/__init__.py
/path/cleverappname/foo.py
/path/cleverappname/bar.py

Assuming you have something like class CleverName(object) in __init__.py and things like class Foo(object) in foo.py (same for bar, you got the idea).

In __main__:

from cleverappname import CleverName
from cleverappname.foo import Foo
from cleverappname.bar import Bar

But, it needs you to use it as a python and not a script (which is right, because that's what it is): python3 -m clevername

Pylint seems happy about that.

like image 145
Arount Avatar answered Nov 13 '22 06:11

Arount