Can not import python modules from package - python

My project path is like:
main.py
modules/
__init__.py
databaseManager.py
sync.py
excel.py
in main.py:
from modules.databaseManger import addExcelToDb, searchInDbAll
from modules.excel import search, showExcelDirContents
from modules.sync import syncExcelAndDB
and for example in database.py :
from modules.excel import showExcelDirContents
from modules.sync import insertExcelNameToSyncDb
but when I run main.py I get this error:
Traceback (most recent call last):
File "main.py", line 6, in <module>
from modules.databaseManger import searchIn
ImportError: cannot import name 'searchInDbAll'
and also having error when trying to import a function from each file in modules directory to others.
I need some examples of importing.

This is circular import issue.
Explanation:
You start by triggering import of databaseManager module.
During this databaseManager code starts to import excel.
During excel importing, excel code tries to retrieve function searchInDbAll() from databaseManager. But at that moment this function does not exist - because databaseManager is in process of importing excel and he hasn't started defining any functions.
How to fix:
In modules where circular import conflicts exist, import modules instead of functions. For example, change this:
from modules.excel import showExcelDirContents
to that:
from modules import excel
And of course, you must then change corresponding function calls, from showExcelDirContents() to excel.showExcelDirContents().
You must do this in your databaseManger, excel and sync modules. With this fix, I actually could run your code.
And yeah, remove appends to sys.path, that is wrong

You can append to your path where you put your modules like this:
import sys
sys.path.append('modules/')
or
import sys
sys.path.append('c:/mycode/stuff/modules/')
note those are forward slashes, or you can use double backslashes like \\
Then just have your databaseManger.py file in /modules
You'll also need to have a file in the /modules folder named:
__init__.py
Which is just an empty file
Then you should be able to do:
from databaseManger import addExcelToDb, searchInDbAll

Related

Cannot import function from another file

I have a file called hotel_helper.py from which I want to import a function called demo1, but I am unable to import it.
My hotel_helper.py file:
def demo1():
print('\n\n trying to import this function ')
My other file:
from hotel.helpers.hotel_helper import demo1
demo1()
but I get:
ImportError: cannot import name 'demo1' from 'hotel.helpers.hotel_helper'
When I import using from hotel.helpers.hotel_helper import * instead of from hotel.helpers.hotel_helper import demo1 it works and the function gets called. I tried importing the whole file with from hotel.helpers import hotel_helper and then call the function with hotel_helper.demo1() and it works fine. I don't understand what's wrong in first method. I want to directly import function rather using * or importing the whole file.
If you filename is hotel_helper.py you have to options how to import demo1:
You can import the whole module hotel_helper as and then call your func:
import hotel_helper as hh
hh.demo1()
You can import only function demo1 from module as:
from hote_helpers import demo1
demo1()
From your fileName import your function
from hotel.helpers import demo1
demo1()
You can import a py file with the following statement:
# Other import
import os
import sys
if './hotel' not in sys.path:
sys.path.insert(0, './hotel')
from hotel import *
NOTE:
For IDE like PyCharm, you can specify the import path using the Project Structure setting tab (CTRL+ALT+S)
Helpful stack overflow questions [maybe off topic]:
What is the right way to create project structure in pycharm?
Manage import with PyCharm documentation:
https://www.jetbrains.com/help/pycharm/configuring-project-structure.html
This is probably a duplicate of: https://stackoverflow.com/posts/57944151/edit
I created two files (defdemo.py and rundefdemo.py) from your posted 2 files and substituted 'defdemo' for 'hotel.helpers.hotel_helper' in the code. My 2 files are in my script directory for Python 3.7 on windows 10 and my script directory is in the python path file python37._pth. It worked.
defdemo.py
def demo1():
print('\n\n trying to import this function ')
rundefdemo.py
from defdemo import demo1
demo1()
output
trying to import this function
I was able to solve the issue, it was related to some imports I was making in my file, when I removed all the import statement in my hotel_helper.py ,the code started working as expected , Still I don't understand reason why the issue was occurring. anyway it works.
This ImportError can also arise when the function being imported is already defined somewhere else in the main script (i.e. calling script) or notebook, or when it is defined in a separate dependency (i.e. another module). This happens most often during development, when the developer forgets to comment out or delete the function definition in the body of a main file or nb after moving it to a module.
Make sure there are no other versions of the function in your development environment and dependencies.

Getting Python import error although the path is correct

detector_main.py
import ast
import os
import fpdf
from Detector.class_coupling_detector import detect_class_cohesion
from Detector.cyclomatic_complexity_detector import detect_cyclomatic_complexity
from Detector.long_lambda_detector import detect_long_lambda
from Detector.long_list_comp_detector import detect_long_list_comp
from Detector.pylint_output_detector import detect_pylint_output
from Detector.shotgun_surgery_detector import detect_shotgun_surgery
from Detector.useless_exception_detector import detect_useless_exception
from tools.viz_generator import add_viz
import sys
def main(directory):
# Get stats for files in directory
stats_dict = get_stats(directory)
...
I have a bunch of imports in this file. When I run this file, (the parameter is a string path to the directory), I get the following error
File "C:\Users\user\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/user/Desktop/project/src/detector_main.py", line 12
from ../tools.viz_generator import add_viz
and my project structure looks like below:
I feel like these inputs are not consistent and could be more organized. I just wrote a bunch of scripts and important that way but I feel like there is a way to make this into a more consistent package where users can run it anywhere with import issues.
Any help?
It sounds like what you're looking for is a Python Package.
https://www.pythoncentral.io/how-to-create-a-python-package/
Working with Python packages is really simple. All you need to do is:
Create a directory and give it your package's name. Put your classes
in it. Create a init.py file in the directory That's all! In order
to create a Python package, it is very easy. The init.py file is
necessary because with this file, Python will know that this directory
is a Python package directory other than an ordinary directory (or
folder – whatever you want to call it). Anyway, it is in this file
where we'll write some import statements to import classes from our
brand new package.
What I do is put my packages in
PYTHON_PATH\Lib\site-packages\MYPACKAGE
then in the __init__.py
from .function_scripts import *

controlling namespaces while importing modules in python

I have split a project that i write from 1 file to several files
The thing is, that i have around 50 classes that I created and are called from the main file, I don't want to rewrite all those class references and add the module name before each class.
I tried to make all those classes accessible through 1 package (Tokens)
So I have
Main.py
Tokens /
__init__.py
Gen.py
BuilltIns.py
The Idea was to populate the package namespace with all the classes, and then import the package inside Main.py
__init__.py:
from Gen import *
from BuilltIns import *
Main.py:
from Tokens import *
When I ran __init__ it works perfectly, and dir() reveals that all class names are imported to package namepace.
However, when i run Main.py, I get the error message:
Traceback (most recent call last):
File "../Main.py", line 1, in <module>
from Tokens import *
File "..\Tokens\__init__.py", line 1, in <module>
from Gen import *
ModuleNotFoundError: No module named 'Gen'
How should I extract the 60+ classes from Main.py to other modules without rewriting all the calls for those classes?
You should use from Tokens.Gen import ... since Tokens is the package where the Gen module resides. The import path should be relative to the main script, unless you've modified the sys.path to specify additional directories to be searched during imports.
Alternatively, in Tokens/__init__.py you can do from .Gen import * (note the . before Gen). This denotes a relative import. What happens when you run the main script is that the current working directory is added to the paths to be searched during imports, so when from Gen import ... is encountered only the default locations are searched (which doesn't include the Tokens directory). By using a relative import you tell Python where it can find that module relative to the current one.
Note that you can define your classes in __all__ in order to constrain what will be imported during from ... import *. This way you don't leak other names in your main script's namespace.

How to import a file from a package which is importing another file from the same package

I've been working on a project where I have a file which needs to call a function from a file in a sub package/directory, which in turn is calling a function from another file in the same sub package. As such, I have a main file which is importing a sub file. This sub file is also importing another sub file which is in the same package.
The first sub file has no issue whatsoever importing the second sub file. The main file also has no issue importing the first sub file. However, when I put it all together and run the main file, Python thinks that the second sub file doesn't exist, which I find strange. I've simplified and visualised my problem with an example below:
I have the following file hierarchy:
test_package\
__init__.py
main_file.py
test_sub_package\
__init__.py
subfile1.py
subfile2.py
main_file code:
import test_sub_package.subfile1
subfile1 code:
import subfile2
subfile2 code:
def get_string():
return ("Hello, World!")
So, I would expect main_file to import subfile2 via subfile1. However this doesn't seem to be the case because I get an error:
Traceback (most recent call last):
File "...\Test\main_file.py", line 1, in <module>
import test_package.subfile1
File "...\Test\test_sub_package\subfile1.py", line 1, in <module>
import subfile2
ModuleNotFoundError: No module named 'subfile2'
I was a little surprised that I got this error before I even attempted to call the functionality in subfile2. Either way, I'm confused why this doesn't work. Am I just doing something stupid here or am I trying to do something Python fundamentally doesn't support. If anyone can give me a solution it would be most appreciated.
I suspect this is probably a duplicate but I couldn't find an answer to my specific problem. So, sorry in advance.
When you import a module into another module from the same directory you must use must use a relative import in subfile1.py you will need to write:
from . import subfile2
Note, that doesn't give subfile 1 access to get_string to use it in subfile1, you would need to either write subfile2.get_string() or import it directly with:
from .subfile2 import get_string
I have tried this out and it works, I hope this helps :)
Note: that, if you are running a python script, and you need to import a module in that same directory, you can just say import module_name. It makes a difference if it is a script you are running, or a module that is being used in some other script. For a detailed explanation as to why see here
(I assume from your error message that you want to run main.py, if this is not the case you will need to change import test_sub_package.subfile1 to from . import test_sub_package.subfile1)
main file should be:
from test_sub_package.subfile1 import get_string
get_string()
subfile1.py
import test_sub_package.subfile2

Unable to import a local project to another local one by absolute path:

I have 2 projects in the different directories, one of them I want to import to another one. Say, the project I want to import has this:
/path123/my_project/main_folder/file1.py
/path123/my_project/main_folder/file2.py
/path123/my_project/main_folder/file3.py
Here's what I did in the 2nd project:
import sys
sys.path.append('/path123/my_project/main_folder')
# it's indeed inserted
import main_folder.file1 # error - not found
from main_folder import file1 # error - not found
import my_project.main_folder.file1 # error - not found
After you appended the path where your second python file that you want to use in your first python file is you directly import the module by its filename without the extension. For example
import file1
Every location in your sys.path is then looked for the file file1.py to import.
Say you have your main python program in /prog1/main.py and you want to import the file from /prog2/lib/want_to_import.py in your main.py it should look like
import sys
sys.path.append('/prog2/lib')
import want_to_import

Categories

Resources