2

Although I think this should be pretty simple I still can't make it run.

I have following folder structure:

├── apartment          
│   ├── src        
│       ├── train_model
│           ├── __init__.py 
│           ├── train_model.py
│           ├── utils.py
│       ├── interference.py
│       └── __init__.py

In utils.py I tried:

from src.interference import create_sample

Error: ModuleNotFoundError: No module named 'src'

from .interference import create_sample

Error: ImportError: attempted relative import with no known parent package

from interference import create_features_sample

ModuleNotFoundError: No module named 'interference'

What is the way to make it work? I am not a huge fan of non-pythonic ways as it looks dirty.

RMPR
  • 3,368
  • 4
  • 19
  • 31
Anni
  • 403
  • 7
  • 19

5 Answers5

1

You need to add the directory that contains interference to PYTHONPATH.

You can use OS depending path in "module search path" which is listed in sys.path. So you can easily add parent directory like following:

import sys
sys.path.insert(0, '..')

from interference import create_features_sample

Note that the previous code uses a relative path, so you must launch the file inside the same location or it will likely not work. To launch from anywhere, you can use Path from the pathlib module.

from pathlib import Path
import sys
path = str(Path(Path(__file__).parent.absolute()).parent.absolute())
sys.path.insert(0, path)

from interference import create_features_sample
RMPR
  • 3,368
  • 4
  • 19
  • 31
  • This would only add the the module temporarily. – BramAppel Feb 12 '20 at 10:26
  • 2
    Which is what they want in most cases. You don't want to pollute your PYTHONPATH with every single random projects + it will be executed when the file is launched, so I don't really see your point here. – RMPR Feb 12 '20 at 10:50
1

The structure starting with a src/ is aimed explicitly at not enabling import by from src.intereference import ..., and you should not put an __init__.py file in src/ folder.

Instead, following nice explanation and examples here: https://blog.ionelmc.ro/2014/05/25/python-packaging/, here is what I recommend:

  • install the package:

    • add a setup.py file at root of your folder (this is clearly not as hard as it seems)
    • maybe create a virtual environment
    • using pip install -e . (with trailing dot!) command
  • then simply import your package by from interference import ...

To answer to your primary request, you could update src/__init__.py with from intereference import create_sample, to expose this function at a higher level, then the chained import would work. However, I do not recommend this, as it renders everything very rigid.

Joël
  • 2,723
  • 18
  • 36
  • Isn't already a __init__ there? The one below interference.py – Bernardo Duarte Feb 12 '20 at 10:32
  • There is indeed, but the structure is kinda weird, hence my proposal for improvement. However, I may have not understood the structure correctly so I may update my answer. – Joël Feb 12 '20 at 10:46
  • 1
    I think we just need to answer how to import interference from utils – Bernardo Duarte Feb 12 '20 at 10:48
  • @Joël After your comment about the weird structure I realized that it is indeed weird, so I changed it . Thank you! – Anni Feb 12 '20 at 12:48
  • @Anni glad I could help! If you found a nice way to structure your project, then you may create a new answer and explain there how it now looks like :) – Joël Feb 12 '20 at 14:37
0

Have you tried from ..interference import create_sample ?

Or for the whole module from .. import interference.

I've checked here, that I'm using another command, something that is missing from the question at the time of writing this. The command that I'm using is python -m src.train_model.utils from apartment folder.

Thanks to RMPR for helping me.

This problem is similar to this one.

RMPR
  • 3,368
  • 4
  • 19
  • 31
Bernardo Duarte
  • 4,074
  • 4
  • 19
  • 34
0

If you want add a custom path to your PYTHONPATH permanently, go to the 'site-packages' folder of your current Python environment and add the file 'custompaths.pth' in which each line should consist of a directory which will then be checked if you try to import the module.

Assuming 'src' being the module you want to import you should add the following line to the .pth file:

your_preceding_path/apartment

BramAppel
  • 1,346
  • 1
  • 9
  • 21
0

Error because of python can't able to find the specific file or package. Python usually find only for the child packages or files, otherwise you need to specify the absolute path.

import sys, os
sys.path.append(os.path.abspath(os.path.join('../..', 'src')))

Please refer the "How to access a module from outside your file folder in Python?"