Python modules import problem: import statement in different location - python

Here's my folder structure:
main.py
tools/
sub1.py
sub2.py
where main.py:
import tools.sub1
import tools.sub2
and sub1.py:
a = 'abc'
and sub2.py (directly import sub1 is not working, is it because I am running main.py from the root directory?):
import tools.sub1
print(tools.sub1)
from here, I knew that in order to correctly call sub1, sub2 from main, we have to add the statement import tools.sub1 in sub2, however, if I want to run sub2 individually, error occurs
Traceback (most recent call last):
File "sub2.py", line 1, in <module>
import tools.sub1 as sub1
ModuleNotFoundError: No module named 'tools'
So, My question is that is it possible to directly run sub2 individually, while keeping the current design that we can properly run main.py?. Thanks in advance.

You can run sub2 using python -m tools.sub2
More info on using -m https://docs.python.org/3/using/cmdline.html#cmdoption-m

You can do this by making tools a python module. Adding an __init__.py file (can be empty) in your tools directory will make Python consider the "tools" folder a module. You can then reference sub1 from both main.py and sub2.py with:
from tools import sub1

Related

How to write a package in Python with modules that reference each other?

I am trying to make a package with modules inside that import each other and I'm very confused on how it works. I made three files: test1.py, test2.py and __init__.py which are contained in my package directory testpack.
The contents of the files are as follows:
# test1.py
def demo():
print("123")
return
# test2.py
import test1
def demo2():
print("test 2")
test1.demo()
if __name__=="__main__":
demo2()
The __init__.py file is left empty. When I run test2.py on it's own I get the expected output:
test 2
123
I also have a main.py file in the parent directory of testpack
# main.py
import testpack.test1
import testpack.test2
testpack.test2.demo2()
Running this gives the error:
Traceback (most recent call last):
File "E:/packages/main.py", line 2, in <module>
import testpack.test2
File "E:\packages\testpack\test2.py", line 1, in <module>
import test1
ModuleNotFoundError: No module named 'test1'
Following some tips I tried running a different version of the code which yielded the same results:
# main.py alternative
from testpack.test2 import demo2
demo2()
What am I missing? My logic was that when importing testpack.test2 Python goes into test2.py where it has to import test1. Importing test1 shouldn't be an issue because we can successfully run test2.py on it's own, so it would construct demo2() using the function from test1, and I'd be all done, but I'm obviously wrong. At one point I thought that running import testpack.test1 before import testpack.test2 could be posing problems because I'd be importing test1 twice (once inside test2 also), but with the alternate version of main not running as well I'm completely lost.
SOLVED: As per MisterMiyagi's suggestion, the solution was to use from . import test1 instead of import test1 in test2.py. The dot specifies that the file to be imported is located in the same directory as the current file, a double dot would specify that the file to be imported is located in the parent directory, etc. I found this article to be helpful https://realpython.com/absolute-vs-relative-python-imports/

Trouble importing a module that itself imports another module in Python

Python version: 3.8.5
File structure
MainDir
|
| Utils --|
| | module1.py
| | module2.py
|
| Tests --|
| test.py
module1.py imports module2.py
test.py imports module1.py
When I run python Tests/test.py I get the following error:
Traceback (most recent call last):
File "test.py", line 5, in <module>
import Utils.module1
File "<abspath>/MainDir/Utils/module1.py", line 16, in <module>
import module2
ModuleNotFoundError: No module named 'module2'
I've tried the following:
1.) Python - Module Not Found
2.)
$export PYTHONPATH="$PWD"
3.) I've tried putting the test.py file at the same level as the Utils directory.
4.)
import sys
sys.path.append("../MainDir")
And several variations thereof.
They all failed.
The only thing that worked was just putting test.py in the Utils directory and running it from there. But I know there has to be a way to get it to work when it's in its own directory.
What am I missing?
UPDATE
The selected answer worked when trying to run test.py, but it broke when trying to run module1.py.
After some more research, running it with the -m flag and package syntax worked; in my case:
python -m Utils.module1
Hope this helps anyone else who runs into this problem.
You may want to use relative imports.
So perhaps something like :
# in module1.py
import .module2
Relative imports mean that you are not trying to import from the __main__ file but from the current file (in your case module1.py).
Edit :
Just realised I am stupid. This works for modules, not individual files.
Please try again with from . import module2
if you structure your project like here you can use this. Also it is recommended to use relative import inside your packages
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

Pycharm cannot import module from Parent folder name

I have project defined in below way:
project/
__init__.py
dog.py
cat.py
In my dog.py, I'm calling:
import project.cat
which gives me this error:
ModuleNotFoundError: No module named 'project'
However, I have setup PYTHONPATH to the parent of project directory, which if I run dog.py outside of Pycharm (for example on the command line) it works well without exceptions.
Now even if I added project folder as Source Root, Pycharm still labels my import statement as wrong (red color) and also doesn't allow me to run it inside Pycharm for dog.py program. This is so confusing. Can anyone help?
*PS: I don't want to use relative imports in dog.py like 'from .cat import *' because I have if name == main statement in dog.py, which python doesn't allow me to run the relative imports inside dog.py.
===============
Adding more information:
I noticed if I made the src folder under project to make the structure like:
project/
__init__.py
src/
__init__.py
dog.py
cat.py
then I can call this in dog.py:
import src.cat
But this way, I am still troubling myself because when I run program in Pycharm, I have to use this way:
import src.cat
when I run program in ipython notebook, I have to import like:
import project.src.cat
This cause me constantly switch my code when I have to run in different places.
=====================
If I simply do this in dog.py
import cat
It will work in Pycharm. But when I call in command line, it's going wrong there now:
In [10]: import project.dog
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-10-be5ebc05b4b0> in <module>
----> 1 import project.dog
~/PycharmProjects/project/dog.py in <module>
2 import pandas as pd
3 import numpy as np
----> 4 import cat
5 from datetime import datetime
6
ModuleNotFoundError: No module named 'cat'
Issue resolved by making my parent folder of my project as the root folder and make root as Source Root.
parent-folder\
project\
__init__.py
dog.py
cat.py
Now it works well on both command line and Pycharm by simply adding one line in .bashrc:
export PYTHONPATH=$PYTHONPATH:~/project

Having Trouble with Import Statement in Python

My current projects are structured like so.
python/
__init__.py
project_1/
__init__.py
program_1.py
project_2/
__init__.py
program_2.py
project_3/
__init__.py
program_3.py
I wanted to import a class from project_3/program_3.py, called INFO, from both project_1/program_1.py and project_2/program_2.py. In both my program_1.py and program_2.py, I've tried the following import statements that didn't work.
Edit - I typically "cd" into project_1 and run my program_1.py from there.
from project_3.program_3 import INFO
Traceback (most recent call last):
File "./program_1.py", line 43, in <module>
from project_3.program_3 import INFO
ImportError: No module named 'project_3'
from python.project_3.program_3 import INFO
Traceback (most recent call last):
File "./program_1.py", line 43, in <module>
from python.project_3.program_3 import INFO
ImportError: No module named 'python'
The only way for me to import class INFO into program_1.py and program_2.py is by copying program_3.py in both program_1 and program_2's folder. My import in program_1 and program_2's statement would become:
python/
__init__.py
project_1/
__init__.py
program_1.py
program_3.py
project_2/
__init__.py
program_2.py
program_3.py
project_3/
__init__.py
program_3.py
from program_3 import INFO
This is quite inconvenience because now I have to update program_3.py in all 3 locations. Assuming my the way I structured my project folder is retarded:
What's the correct/best way to structure my folders so that I could call program_3.py from program_1/2.py?
If there's nothing wrong with my current structure, how do I correctly import the INFO class into program_1/2.py?
I have read the python documentation but it didn't say anything regarding importing classes from one subfolder to another. I also looked at another post from Stack Overflow as well but it didn't have the same structure as mine.
Update 1 - It's important to note that I'm merely using project_1/2 as folder to organized my projects. I originally had init.py in all my folders because I have no clue what I'm doing. The only module/package that I wanted to import in my project_1/program_1.py is from project_3/program_3.py. Example:
python/
project_1/
program_1.py
project_2/
program_2.py
project_3/
__init__.py
program_3.py
When using submodules, you need to use relative imports. In the example provided, importing program_3 from program_1 should be :
from ..project_3 import program_3
and then you can use the INFO class: program_3.INFO.
This works if your executable file is outside the script, that is the file which uses the module python in the example should be outside the python module.
If parts of the python package are executed as a script, the -m option should be passed to the interpreter:
python3 -m python.project_1.program_1
I hope this helps.
The previous solution provides me the same error.
I found a fix by using sys:
import sys
sys.path.append('../')
from project_3 import program_3
...
This way, you setup 'python' folder as reference (in your case it's the parent folder but you can select the path you want)
I hope it helps,

Import from different directories in python

This is my folder structure:
src/
__init__py
Lowlevel/
__init__.py
ModuleToCheck.Py
Test/
__init__.py
ModuleToCheck_test.py
(__init__.py are empty files)
Now I want to import ModuleToCheck.py in ModuleToCheck_test.py
How am I able to do this without appending anything to sys.path?
Update:
from ..Lowlevel import ModuleToCheck leads to:
src$ python Test/ModuleToCheck_test.py
Traceback (most recent call last):
File "Test/ModuleToCheck_test.py", line 6, in <module>
from ..Lowlevel import ModuleToCheck
ValueError: Attempted relative import in non-package
The following is from http://docs.python.org/tutorial/modules.html#intra-package-references
Note that both explicit and implicit
relative imports are based on the name
of the current module. Since the name
of the main module is always
"__main__", modules intended for use
as the main module of a Python
application should always use absolute
imports.
You're running your module ModuleToCheck_test.py as the main module, hence the exception.
One solution is to create a test.py module in your src directory containing the following:
import Test.ModuleToCheck_test
You can then run that module using python test.py

Categories

Resources