0

I've tried too many solutions that are provided here on SO but wasn't able to make this work.

here is directory structure.

|project
|------->folder1
|-------------->file1.py   #file1.py contains class File1
|-------------->file2.py   #file2.py contains class File2
|------->folder2
|-------------->another_file1.py   #another_file1.py contains class SomeClass1
|-------------->another_file2.py   #another_file2.py contains class SomeClass2
|------->Runner
|-------------->logic.py

I need to create instance of all the classes here in logic.py I created __init__.py in all folders, and one in the main project.

__init__.py # folder1

from . import file1
from . import file2

__init__.py # folder2

from . import another_file1
from . import another_file2

__init__.py # project

from . import folder1
from . import folder2

I'm unable to import any of stuff inside Runner. I get following errors.

No module named file1.

No module named file2.

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

However I can make it to work by this tweak.

import sys
sys.path.append('../')

in my files inside Runner directory. But I don't want to do this in my every file.

P.S. using Python 3.5

Mubin
  • 4,325
  • 5
  • 33
  • 55
  • 1
    If you're using relative imports it should be `from ..folder1 import blah` or `from ...project import blah` – gold_cy Apr 17 '17 at 10:58
  • @DmitryPolonskiy: using `..` or `...` gives the same error. `SystemError: Parent module '' not loaded, cannot perform relative import` – Mubin Apr 17 '17 at 11:01
  • 1
    I don't think there is a good way to deal with this without using that tweak or relative path. While you use popular frameworks, tools, libraries, most of those projects put runner in the top-level folder. Thus for the best practice, you should put runner in the top-level folder. – Kir Chou Apr 17 '17 at 11:03
  • @KirChou: yes this seems to be the only options for now, but I'm curious what if [in future] I create a new folder `Commons` and it can contain multiple classes under. The same issue will arise if then I try to load something from `Commons` to `folder1` etc.. Hope you got my point. – Mubin Apr 17 '17 at 11:05
  • @Mubin another way, and not recommended would be to add the path of those files you're trying to import from to your path, you seemed to try to be doing that in your code but all you added was a slash. – gold_cy Apr 17 '17 at 11:07
  • @DmitryPolonskiy: `sys.path.append('../')` if I add this, it works fine, but as you mentioned, not recommended way to do so. – Mubin Apr 17 '17 at 11:10
  • @Mubin In my previous experience, I sometimes use `softlink` to solve this kinda problems, however those including above are not good ideas. The best way is design your project's directory structure carefully at the beginning. – Kir Chou Apr 17 '17 at 11:12
  • Check out http://stackoverflow.com/questions/16981921/relative-imports-in-python-3 – Claudio Apr 17 '17 at 17:17

1 Answers1

0

Anyone coming across the same issue, can do something like this.

1) create new project e.g: StreamingApplication.

|root --StreamingApplication
|-------> utils
|-------------->helper.py
|-------------->storage_handler.py
|------->config
|-------------->config.py
|-------------->hook.py
|------->app
|-------------->application.py

So, you can also create __init__.py file if you want to mark folder as python package.

add project root path to PYTHONPATH system variable.

in ~/.bashrc or /etc/profile

export PYTHONPATH=/path/to/StreamingApplication

source file with source ~/.bashrc or source /etc/profile

then in application.py you can do something like this.

from utils.helper import write_file #write_file is function.
from utils.storage_handler import StorageHandler # StorageHandler is class
import config as conf

class App:
    def __init__(self):
        self.executors = conf.executors  # access  executors variable from config

All set.

Mubin
  • 4,325
  • 5
  • 33
  • 55