Python - importing a class within the same folder - python

I use python 3.5 with Anaconda (python 3.6) and I have a problem with importing a class within the same folder, even though I did exactly as explained in other places.
In 04-Convolutional Neural Network Folder I have
04-Convolutional Neural Network.ipynb and logger.ipynb files.
I want to import Logger class in logger.ipynbto 04-Convolutional Neural Network.ipynb
First, I created a blank __init__.ipynb file in the same folder, I used:
from .user import User
from .dir import Dir
But I get the following error
No module named '__main__.user'; '__main__' is not a package
Any idea why do I have this problem? maybe because of the ipynb file system?
Edit: The files are in Desktop/NN/.... if it's important

It seems to refer to the file your running (namely main). I don't use relative import much. But if user and dir are in the same directory as the file your running you should try (i.e. they are in the root of your python module):
from user import User
from dir import Dir
You should probably also rename the dir module, as dir is a builtin function in python.

Related

VSCode Python error in importing modules from subdirectories

My project file structure is like this,
project/src/test/myscript.py
project/src/utils/file_utils.py
When I run myscript.py, which has from utils import file_utils, it gave me error:
ModuleNotFoundError: No module named 'utils'
Previously in Pycharm IDE I did not get this type of error (maybe due to _ init _.py), the subdirs of the same parent dir could be detected. But not sure for VSCode, is there something I need to add for specifying the file structure? And I opened the folder project as my VSCode workspace (not sure if where I open the workspace matters)
I tried adding:
in the /project/.vscode/launch.json
"cwd": "${workspaceFolder}/src"
or in the begining of myscript.py
import sys
import os
src_path = os.path.dirname(os.path.abspath('/project/src/'))
sys.path.insert(0, src_path)
But none of them works. Does anyone have any insights? Thank you very much!
You could consider placing a .env file at the root of your project which adds your source directory to PYTHONPATH. i.e. something like
>>> cat /project/.env
PYTHONPATH=/project/src/
>>>
Your code will look a smidgen nicer without the explicit manipulation of sys.path.
VSCode's usage of .env files is documented here.
Yes, in Pycharm you didn't get this error because it adds __init__.py file automatically when you create a python module. The python identifies the structure of your project through these files, if your folder does not have __init__.py python will understand it as just any folder.
Unlike pycharm, vscode uses the workspace as the root directory to retrieve files. The first method you try is to write it in the launch.json file, which is applicable to debug rather than running it directly. You can use the following code to import:
from src.utils import file_utils

Dynamic Importing with Pyinstaller Executable

I’m trying to write a script that dynamically imports and uses any modules a user places in a folder. The dynamic importing works fine when I’m running it via python, but when I try to compile it into a Pyinstaller executable, it breaks down and throws me a ModuleNotFoundError, saying it can't find a module with the same name as the folder the modules are placed in. The executable sits alongside this folder, which contains all the modules to be dynamically imported, so my import statements look like __import__("FOLDERNAME.MODULENAME"). The script must be able to run the modules dropped in this folder without being recompiled. What's strange is that the ModuleNotFoundError says No module named 'FOLDERNAME', despite that just being the name of the folder containing the modules, I'd expect it to complain about No module named 'FOLDERNAME.MODULENAME' instead.
In my googling, I found this question (pyinstaller: adding dynamically loaded modules), which is pretty similar, but the answer they provided from the docs doesn’t really help. How do I give additional files on the command line if I don’t know what files are going to be in the folder in the first place? That kind of beats the purpose of dynamic importing. I've attempted to use the hidden-import command line flag, but the compiler output said Hidden import '[X]' not found. Maybe I'm just using it wrong? And I have no idea how to modify the spec file or write a hook file to do what I need. Any help would be greatly appreciated.
I was working on a similar functionality to implement a Plugin Architecture and ran into the same issue. Quoting #Gao Yuan from a similar question :-
Pyinstaller (currently v 3.4) can't detect imports like importlib.import_module(). The issue and solutions are detailed in Pyinstaller's documentation, which I pasted below as an entry point.
But of-course there is always a way. Instead you can use importlib.util.spec_from_file_location to load and then compile the module
Minimum wokring example
iterface.py
# from dependency import VARIABLE
# from PySide6.QtCore import Qt
def hello_world():
print(f"this is a plugin calling QT {Qt.AlignmentFlag.AlignAbsolute}")
print(f"this is a plugin calling DEPENDENCY {VARIABLE}")
cli.py
import sys
import types
from pprint import pprint
import importlib.util
import sys
if __name__ == "__main__":
module_name = "dependency"
module_file = "plugins/abcplugin/dependency.py"
if spec:=importlib.util.spec_from_file_location(module_name, module_file):
dependency = importlib.util.module_from_spec(spec)
sys.modules[module_name] = dependency
spec.loader.exec_module(dependency)
module_name = "interface"
module_file = "plugins/abcplugin/interface.py"
if spec:=importlib.util.spec_from_file_location(module_name, module_file):
interface = importlib.util.module_from_spec(spec)
sys.modules[module_name] = interface
spec.loader.exec_module(interface)
sys.modules[module_name].hello_world()
project structure
cli.exe
plugins
abcplugin
__init__.py
interface.py
dependency.py
complus
__init__.py
...
Thumb Rules
Plugin must always be relative to .exe
As you can notice I commented out # from dependency import VARIABLE in line one of interface.py. If you scripts depend on scripts in the same plugin, then you must load dependency.py before loading interface.py. You can then un-comment the line.
In pyinstaller.spec file you need to add hiddenimports in this case PySide6 and then un-comment # from PySide6.QtCore import Qt
Always use absolute imports when designing a plugin in reference to your project root folder. You can then set the module name to plugins.abcplugin.interface and plugins.abcplugin.dependency and also update from dependency import VARIABLE to from plugins.abcplugin.dependency import VARIABLE
Hope people find this usefull, cheers!!

Module not found even though explicitly added to system path

I am trying to use Lumerical in python. Lumerical is an electromagnetic simulation software that allows access via python. For more information, please refer to https://support.lumerical.com/hc/en-us/articles/360041873053
Anyway, to make it run, I need to import a module called lumapi. It's located in the program's directory:
C:\Program Files\Lumerical\v202\api\python\lumapi.py
So, naturally, to import it into my current script file, I used the following code:
import sys
sys.path.append(r"C:\Program Files\Lumerical\v202\api\python\lumapi.py")
import lumapi
But I got:
ModuleNotFoundError: No module named 'lumapi'
What I have tested
When I save the script file directly inside the folder where
lumapi is stored and just write import lumapi it works.
With sys.path I have tested if the directory was indeed added to
the path, and it seems to be the case
I also made sure that I have full write and read permission to the
folder where lumapi is stored

Can not import class from another folder

I have a similar issue as this Can't get Python to import from a different folder The solution there doesn't solve my issue.
I'm working with Airflow lib. The lib updated one of the operators and since I can not at this time upgrade the my Airflow version I want to manually download the operator .py file and use it in my code manualy.
airflow
-dags
--mydag.py
-AddedOperators
--sagemaker_tuning_operator.py
--__init__.py (empty file)
The sagemaker_tuning_operator.py is this file:
https://github.com/apache/airflow/blob/master/airflow/contrib/operators/sagemaker_tuning_operator.py
It contains the class SageMakerTuningOperator
In my mydag.py I do:
from AddedOperators.sagemaker_tuning_operator import SageMakerTuningOperator
When Airflow try to parse mydag.py I get:
No module named AddedOperators.sagemaker_tuning_operator
Check if your project directory is in your system path or not. You can can check it as follows:
import sys
print(sys.path)
Note that when running a Python script, sys.path doesn’t care what
your current “working directory” is. It only cares about the path to
the script. For example, if my shell is currently at the Airflow/
folder and I run python ./dags/mydag.py, then sys.path includes
Airflow/dags/ but NOT Airflow/
If you project directory is not in sys path, you can do following:
Include it dynamically.
import sys
sys.path.insert(0, 'path/to/your/')
# import your module now
Import all required modules in your project root folder in some file like app.py and then call from here.

Import classes/functions from Python files saved in same folder showing "No Module Named" error

As per screen print, import shows error in Python 3.7 version, earlier it was working fine in version Python 2.7 and I am using IntelliJ Idea.
If you see, EOC related .py files are in the same folder and have classes which are being called in Main_EOC.py by passing objects which are inter-related. It's amazing to see the red line while importing files from same folder.
Please help me why it's showing such error
"This inspection detects names that should resolve but don't. Due to dynamic dispatch and duck typing, this is possible in a limited but useful number of cases. Top-level and class-level items are supported better than instance items.`"
Also, if you see the line which have full path, is not showing error
from EOC_Module.eoc.script.config import Config
Please help me if there is a way to add this full path on top of the code or other option.
The behavior of import path search changed between python2 and python3. The import path always includes the directory from which the main module was loaded, but it no longer includes directories from which modules were imported.
You need to change your import statement syntax as follows, if you want to import a module that lives in the same directory as the module in which you do the import:
# old way, import works if the named module is in this module's directory
import x
# new (Python3) way:
from . import x
For the second part: adding a path so all code can import from a certain directory: if that directory is (and will always be) relative to your main: you can add a few lines in the main module to make it available. Something like this:
import sys # if you haven't imported it already
import os.path
home = os.path.dirname(sys.argv[0])
sys.path.append( os.path.join(home, "EOC_Module/eoc/script") )
# now, you can import straight from the script directory
import EOC_Intraction
When using pycharm the root directory for your python executable is the same as the root directory of your project, this means that python will start looking for files in the root directory with this files:
.idea/
EOC_module/
logs/
reports/
sql/
This is the reason of why: from EOC_Module.eoc.script.config import Config works.
If you execute your code from the terminal with: python3 Main_EOC.py (not pycharm) the root directory for your python will be the same as the one containing the file, all the other imports will work but from EOC_Module.eoc.script.config import Config not.
So you need to make your imports from project directory if you are using pycharm.

Categories

Resources