how to import custom modules in Cloud Composer - python-3.x

I created a local project with apache Airflow and i want to run it in cloud composer. My project contains custom modules and a main file that calls them.
Example : from src.kuzzle import KuzzleQuery
Structure:
main.py
src
kuzzle.py
I have imported my project folder in data storage and when i refreshed the UI of airflow composer i've got this error:
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/home/airflow/gcs/dags/quality-control/main.py", line 8, in <module>
from src.kuzzle import KuzzleQuery, Tag
ModuleNotFoundError: No module named 'src' ```

Try adding an __init__.py file inside src directory to make it a module.

GCP Composer is loading the dags folder as a python module, so you can just put your code there in a separate file or folder and it will work as usual referencing it from the dags.
dags/
dag1.py
util.py
Then you can reference util and import it from dag1 as:
from util import custom_function
If dags folder does not work for you composer also loads more directories like the ones for loading modules.
You can also check this question since it is also related.
Airflow dag dependencies not available to dags when running Google's Cloud Compose

You could check these options:
The path of the module is not correct
Probably, you would want to import a module file, but this module is not in the same directory.
For example:
Project Structure
core.py
folder_1
---module.py
We want to import the module.py
Core.py
import module.py #incorrect
Output:
ModuleNotFoundError: No module named 'module'
Core.py
import folder_1.module.py #correct
Output:
...Program finished with exit code 0
The library not Installed
If you want to import a module of a library which is not installed in your virtual environment before importing a library's module, you need to install it with the pip command. You could see this documentation:
For example, import Beautifulsoup4 library it is not installed
>>> from bs4 import BeautifulSoup
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'bs4'
Now, let's install the library and try to re-import it
Installing:
pip install beautifulsoup4
Collecting beautifulsoup4
Using cached https://files.pythonhosted.org/packages/d1/41/e6495bd7d3781cee623ce23ea6ac73282a373088fcd0ddc809a047b18eae/beautifulsoup4-4.9.3-py3-none-any.whl
Requirement already satisfied: soupsieve>1.2; python_version >= "3.0" in /home/py/Desktop/seo_pro/seo_env/lib/python3.6/site-packages (from beautifulsoup4) (1.9.5)
Installing collected packages: beautifulsoup4
Successfully installed beautifulsoup4-4.9.3
Re-importing:
>>> from bs4 import BeautifulSoup
>>>
Setup your files as packages and modules
You need to properly set up your files as packages and modules.
Packages are a way of structuring Python’s module namespace by using “dotted module names”. For example, the module name A.B designates a submodule named B in a package named A. Just like the use of modules saves the authors of different modules from having to worry about each other’s global variable names, the use of dotted module names saves the authors of multi-module packages like NumPy or Pillow from having to worry about each other’s module names.
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
You could see more information.

Related

How to write the correct path for importlib in my pip installed python package?

I am trying to create a package where when I call a module a certain class from a python file is automatically loaded, but I can not figure out how to set the correct path with importlib. I try to load the package after installing it with pip install.
In the subfolder pkg_sub, I have __init__.py and testfile.py.
The __init__.py contains this code:
import importlib
pkclass = getattr(importlib.import_module('testfile'), 'pkclass')
And 'testfile.py' contains this code:
class pkclass:
# Some generic print commands for testing.
When I import pkg_sub, I get the error that importlib can not find testfile.py.
I am still confused with how pathing works. I also tried this line in __init__.py:
import importlib
pkclass = getattr(importlib.import_module('.testfile'), 'pkclass')
But then importlib wants to have a package directory in addition to testfile.py. But there are no additional subfolders that I could point importlib to.
Overall, I am just confused how I have to write the path here so that I can make the class directly accessible when I load the module. Any help would be appreciated.

AttributeError when packaging python library

I'm in the process of learning how to package a python library using the official guide. I've started cloning the minimal sample package suggested in the guide here. I've then added the file my_module.py inside the folder sampleproject storing a simple power function. Another function is also stored in /sampleproject/sampleproject/__init__.py. The resulting structure of the library is the following
Finally, I've used pip to successfully install the package in the interpreter. The only thing left is to make sure that I'm able to run the functions stored in the subfolder sampleproject.
import sampleproject
sampleproject.main()
# Output
"Call your main application code here"
This is great. The package is able to run the function in __init__.py. However, the package is not able to find module.py:
import sampleproject
sampleproject.module
# Output
AttributeError: module 'sampleproject' has no attribute 'module'
I've tried to add __init__.py in the main folder and to change the settings in entry_points in setup.py without success. What should I let sampleproject to be able to find the function in module.py?
Your sampleproject.module is a function you would like to execute?
In this case, do as for the sampleproject, add () to execute it:
sampleproject.module()
Otherwise, you can import your package like this:
import sampleproject.module
or:
from sampleproject import module
To be clearer, you would have to import module in your sampleproject __init__.py. Then, when you want to use the package, import it (is some py file at root):
import sampleproject # is enough as it's going to import everything you stated in __init__.py
After that, you can start to use what's in the package you imported with maybe module() if you have a function called module in your package.
init.py discussions
it seems,
you are in sampleproject->module.py
so you need to try,
from sampleproject import module

Python module not recognizing files in the same folder

I've made (at least tried) a package using setuptools and attempted to use it from another python-file. However, the modules within the packages don't seem to recognize each other.
Tree
pkg
|-- pkg
| |-- __init__.py
| \-- module.py
\-- setup.py
__init__.py:
import module
#code
pyfile.py
import pkg
#code
When I attempt to run pyfile.py, I get
Traceback (most recent call last):
File "/.../py/pyfile.py", line 1, in <module>
import pkg
File "/.../pkg/pkg/__init__.py", line 1, in <module>
import module
ModuleNotFoundError: No module named 'module'
It works fine if I write import pkg.module, but I don't see why self.referential code would be practical.
Change the import in your __init__ to
from . import module
You can read more about intra-package references in the python documentation.
(BTW, as far as I can tell, setuptools is not involved here.)

ModuleNotFoundError: No module named '__main__.xxxx'; '__main__' is not a package

Currently trying to work in Python3 and use absolute imports to import one module into another but I get the error ModuleNotFoundError: No module named '__main__.moduleB'; '__main__' is not a package. Consider this project structure:
proj
__init__.py3 (empty)
moduleA.py3
moduleB.py3
moduleA.py3
from .moduleB import ModuleB
ModuleB.hello()
moduleB.py3
class ModuleB:
def hello():
print("hello world")
Then running python3 moduleA.py3 gives the error. What needs to be changed here?
.moduleB is a relative import. Relative only works when the parent module is imported or loaded first. That means you need to have proj imported somewhere in your current runtime environment. When you are are using command python3 moduleA.py3, it is getting no chance to import parent module. You can:
from proj.moduleB import moduleB OR
You can create another script, let's say run.py, to invoke from proj import moduleA
Good luck with your journey to the awesome land of Python.
Foreword
I'm developing a project which in fact is a Python package that can be installed through pip, but it also exposes a command line interface. I don't have problems running my project after installing it with pip install ., but hey, who does this every time after changing something in one of the project files? I needed to run the whole thing through simple python mypackage/main.py.
/my-project
- README.md
- setup.py
/mypackage
- __init__.py
- main.py
- common.py
The different faces of the same problem
I tried importing a few functions in main.py from my common.py module. I tried different configurations that gave different errors, and I want to share with you with my observations and leave a quick note for future me as well.
Relative import
The first what I tried was a relative import:
from .common import my_func
I ran my application with simple: python mypackage/main.py. Unfortunately this gave the following error:
ModuleNotFoundError: No module named '__main__.common'; '__main__' is not a package
The cause of this problem is that the main.py was executed directly by python command, thus becoming the main module named __main__. If we connect this information with the relative import we used, we get what we have in the error message: __main__.common. This is explained in the Python documentation:
Note that 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 must always use absolute imports.
When I installed my package with pip install . and then ran it, it worked perfectly fine. I was also able to import mypackage.main module in a Python console. So it looks like there's a problem only with running it directly.
Absolute import
Let's follow the advise from the documentation and change the import statement to something different:
from common import my_func
If we now try to run this as before: python mypackage/main.py, then it works as expected! But, there's a caveat when you, like me, develop something that need to work as a standalone command line tool after installing it with pip. I installed my package with pip install . and then tried to run it...
ModuleNotFoundError: No module named 'common'
What's worse, when I opened a Python console, and tried to import the main module manually (import mypackage.main), then I got the same error as above. The reason for that is simple: common is no longer a relative import, so Python tries to find it in installed packages. We don't have such package, that's why it fails.
The solution with an absolute import works well only when you create a typical Python app that is executed with a python command.
Import with a package name
There is also a third possibility to import the common module:
from mypackage.common import my_func
This is not very different from the relative import approach, as long as we do it from the context of mypackage. And again, trying to run this with python mypackage/main.py ends similar:
ModuleNotFoundError: No module named 'mypackage'
How irritating that could be, the interpreter is right, you don't have such package installed.
The solution
For simple Python apps
Just use absolute imports (without the dot), and everything will be fine.
For installable Python apps in development
Use relative imports, or imports with a package name on the beginning, because you need them like this when your app is installed. When it comes to running such module in development, Python can be executed with the -m option:
-m mod : run library module as a script (terminates option list)
So instead of python mypackage/main.py, do it like this: python -m mypackage.main.
In addition to md-sabuj-sarker's answer, there is a really good example in the Python modules documentation.
This is what the docs say about intra-package-references:
Note that 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 must always use absolute imports.
If you run python3 moduleA.py3, moduleA is used as the main module, so using the absolute import looks like the right thing to do.
However, beware that this absolute import (from package.module import something) fails if, for some reason, the package contains a module file with the same name as the package (at least, on my Python 3.7). So, for example, it would fail if you have (using the OP's example):
proj/
__init__.py (empty)
proj.py (same name as package)
moduleA.py
moduleB.py
in which case you would get:
ModuleNotFoundError: No module named 'proj.moduleB'; 'proj' is not a package
Alternatively, you could remove the . in from .moduleB import, as suggested here and here, which seems to work, although my PyCharm (2018.2.4) marks this as an "Unresolved reference" and fails to autocomplete.
Maybe you can do this before importing the module:
moduleA.py3
import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from moduleB import ModuleB
ModuleB.hello()
Add the current directory to the environment directory
Just rename the file from where you run the app to main.py:
from app import app
if __name__ == '__main__':
app.run()
import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
will solve the issue of import path issue.

How to create package in python 3.5.1?

I have tried to create a package using python 3.5.1 , but got the error when i import the package.
Traceback (most recent call last):
File "Pack.py", line 2, in
import Com
File "C:\Users\admin\Document\Python\packages\Com__init__.py",
line 2, in
from Algebra import *
ImportError: No module named 'Algebra'
To import a package you created named Algebra, your folder structure should look similar to this:
C:\Users\admin\Document\Python\packages\
Com__init__.py
Algebra\
__init__.py
.
.
.
Alternatively, you can put the Algebra packages parent directory on python's sys.path.
You'll likely run into another issue once you resolve this, which is you cannot import * from the Algebra package without specifying the all trait in Algebra's init.py file. Specifying this done like the following, but replacing the values of the list with your module names:
__all__=['add', 'subtract', 'multiply']
Source: https://docs.python.org/3/tutorial/modules.html#packages

Resources