Module not found error when importing - python

I am trying to import * from a file classes.py. My directory is as follows
mypkg
├── main.py
├── classes.py
When I try
from classes import *
It does not recognise classes. Looking it up I saw that I should use the explicit import
from .classes import *
which does recognise classes but gives the error below when I try to run it.
ModuleNotFoundError: No module named '__main__.classes'; '__main__' is not a package
Any advice on what to do and why this is happening would be hugely appreciated.

For python to recognize a folder as a package, you need an __init__.py file in it:
mypkg
├── __init__.py
├── main.py
├── classes.py
The directory where python is invoked is also important (running from inside a package folder is different to running from outside), and there's the PYTHONPATH environment variable as well.
The python documentation as a section on import and the package system, with good explanations.

Related

Importing a Python module from subfolder of another folder using relative path

I have the following folder structure,
└── project
├── A
│ ├── main.py
│ └── __init__.py
└── B
├── __init__.py
├── C
├── __init__.py
└── module_x.py
I want to import all the methods in module_x.py into main.py. I have tried
from ..B.C.module_x import *
But I get the following error:
ImportError: attempted relative import with no known parent package
I wonder what am I doing wrong? How can this be done using relative import?
from project.B.C import foo
from ...b.c.module_x import foo
However, relative imports are only meant to work within one package. If project is a package, then you can use relative imports here. If project is not a package, you cannot.
However, if you're running a script in / and doing something like import project.A.b.foo, then that relative import will succeed because project is now a package. In that case, the following two would be equivalent:
from ...B.C import foo
from project.B.C import foo
You must use the -m switch to run python modules as scripts:\
$ cd project
$ python -m A.main # note no .py
This tells python that A.main is a module - python will also scan the current working dir (project) and detect package B - this will make your imports work correctly.

Importing module from subfolder

This is the structure of my project
final
├── common
├── __init__.py
├── batch_data_processing.py
├── processing_utility.py
├── post_processing.py
├── Processing_raw_data
├── batch_process_raw_data.py
so i want to import from common.batch_data_processing in batch_process_raw_data.py
but when I try it I get ModuleNotFoundError: No module named 'common'
is there a way to import this module without the need to install it ?
Note : this is intended to be used by "non python users"
here is pictures to better discribe the problem.
Add the following code above your import code to indicate the path:
# The following is a relative path,
# it can also be replaced with the absolute path
# of the directory where common is located.
# sys.path.append("C:\\Users\\Admin\\Desktop\\Final")
import sys
sys.path.append("./")
When all your scripts are in the same folder, importing modules is almost impossible to go wrong. If you need to import scripts from external folders, you can specify the path using the above method.

Import top level file inside subdirectory

I have the following structure in my Python project:
project
├── subdir
│ ├── __init__.py
│ └── script_to_run.py
├── __init__.py
└── functions.py
In script_to_run.py file, I want to import a function from top-level functions.py file as
from functions import function_to_import
When I try to run the script from either root directory (project) or its subdirectory (subdir), I get the following error:
ModuleNotFoundError: No module named 'functions'
How do I import it then?
I've seen several approaches, including messing with your sys.path or installing your local package through pip, but that seems like too much work for something this simple, right?
Python packages are a great thing, but come at a cost: you cannot directly run a file lying deep in the package.
If the file is imported from the package, the correct way would be:
from ..functions import function_to_import
If the file is intended to be launched as a top level script, it should not be in the package. If you really want to go that way, the solution is to add the project directory to sys.path and use:
from functions import function_to_import
but it is an anti-pattern... You have been warned...

Clashing imports between Python modules

I have the following directory structure:
.
├── main.py
├── package
│ ├── module.py
│ └── utils.py
└── utils.py
Inside package, I have (lots of) code in which all imports are relative to package, e.g. package/module.py contains import utils, and it expects to import package/utils.py (not utils.py).
All the code outside package expects imports to be relative to the root directory ..
This is causing an issue for me because if main.py contains import package.module and I have PYTHONPATH=., then package/module.py ends up importing utils.py instead of the desired package/utils.py (since it contains import utils).
How do I resolve this without having to rename scripts? I would like to install the code in package in a way so that I can import it in main.py without its imports clashing with my other files.
What I tried: I added a minimal setup.py file inside package and ran pip install -e . but that didn't resolve the issue.
Thanks a lot for the help!
Have you tried a relative import for Submodules?
So that in general you would use
import utils # Import ./utils.py
import .utils # Import relative ./<eg. package>/utils.py
That would cause Scripts under 'package' to always import their local utils.py

Not able to import module from other directory in Python 3.7.1

I have a package structured as:
Classes in those packages are named exactly like the file names. Also, init.py has following code
from tableau_util import tableau_util
from sftp_util import sftp_util
from s3_util import s3_util
I have another file e.g. test.py which is outside this folder 'utils'. I want to import those classes into test.py so my code is
from utils.tableau_util import tableau_util
from utils.sftp_util import sftp_util
from utils.s3_util import s3_util
I am still getting the error:
ModuleNotFoundError: No module named 'tableau_util'
What can I try to resolve this?
Without knowing everything I would guess that you are trying to run your test.py as a normal python script. Given this folder structure
.
├── __init__.py
├── test
│   ├── __init__.py
│   └── test.py
└── utils
├── __init__.py
├── s3_util.py
└── tableau_util.py
with these files test.py
from utils.s3_util import s3_util
from utils.tableau_util import tableau_util
s3_util()
tableau_util()
import sys
print(sys.path)
s3_util.py
def s3_util():
print('Im a s3 util!')
tableau_util.py
def tableau_util():
print('Im a tableu util!')
if you just tried to run python test/test.py in the main folder it will give you the ModuleNotFoundError. That's because it sets the ./test folder as the python path and it won't be able to see the utils folder and therefore be able to import it. However if you run it as python -m test.test (note the lack of .py you don't need it when you run it as a module) that will tell python to load it as a module and then it will run correctly with this output:
Im a s3 util!
Im a tableau util!
If you don't want to put the test.py in another folder you can simply keep it in the parent folder of utils and be able to run it in the traditional python test.py and get the same results. Error while finding spec for 'fibo.py' (<class 'AttributeError'>: 'module' object has no attribute '__path__') has some more reading on the matter.
For the record all my __init__.py files are empty and don't import anything and this is normally how they are setup unless you want to specify certain functions that need to be imported when the module is imported automatically.
I used PyCharm's create package option to create folders and files again and it is working now. Here are my new (working) folder structure:
My main script has following lines of code to import those classes:
from utils_pkg import tableau_util
from utils_pkg import s3_util
from utils_pkg import sftp_util
First, inside __init__.py (or in any sub-module that tries to import one of its siblings from the same package) you should add a "relative import" dot to the beginning of the module name, so that it reads:
from .tableau_util import tableau_util
# ^right here
Second, make sure your current working directory is not utils. A good place to start, for testing, might be to cd to the parent directory of utils instead.

Categories