Resolve relative import in own module - python

helloPython
__init__.py
myutil
__init__.py
mymaths.py
service
__init__.py
cal.py
mymaths.py
def myadd(a, b):
return a+b
cal.py
from ..myutil import mymaths #or any other similar import statement
sum = mymaths.myadd(3, 4)
Here, in cal.py, I want to use a method defined in mymaths.py as above
However when I try to import, I get below error, when I "Run Python file in terminal" in VSCode Tried multiple ways
First method
from ..myutil import mymaths
ImportError: attempted relative import with no known parent package
Second method
from helloPython.myutil import mymaths
ModuleNotFoundError: No module named 'helloPython'

Relative imports in Python 2.7 and ImportError: attempted relative import with no known parent package helped me to understand. Thanks to #napuzba
and #martineau

Related

ImportError: attempted relative import with no known parent package PYTHON

I am trying to import some functions and variables from the parent directory.
Here is what my dir looks like:
I want the import:
-- send_invoice func from bifatura_methods.py
-- start func from xml_generator.py
-- data_json_1, data_json_2 dicts from inputs.py
TO send_ticari_satis_invoice.py.
My working dir is:
/home/selman/PycharmProjects/15.0/custom_addons/Invoice_Integration/models/tests
When I tried for imports like:
from ..bifatura_methods import send_invoice
from ..xml_generator import start
from inputs import data_json_1, data_json_2
Output:
ImportError: attempted relative import with no known parent package
When I tried this:
from custom_addons.Invoice_Integration.models.bifatura_methods import send_invoice
from custom_addons.Invoice_Integration.models.xml_generator import start
from custom_addons.Invoice_Integration.models.tests.inputs import data_json_1,data_json_2
Output:
ImportError: cannot import name 'models' from 'odoo' (unknown location)
Any advice and help are welcome! Thank you community :)
since your \tests is essentially a module you're importing into, you should add an empty __init__.py inside \tests.
I personally would use explicit imports:
from models.bifatura_methods import send_invoice
from models.xml_generator import start
IMO, this would help you keep your sanity if you end up having a lot more submodules.
You can check the Odoo guidelines that we use from odoo.addons to import from Odoo addons (custom addons should also work)
Example:
from odoo.addons.Invoice_Integration.bifatura_methods import send_invoice

Not able to import a class from a another package in python

* myproject
+ getdir
- somename.py
+ pushdir
- nicename.py
I'm trying to import a class from somename.py into nicename.py.
At first I created the the __init__.py file and left it empty.
Then I wrote (in nicename.py):
from ..getdir.somename import classnameexample
and I also tried the command without double points at first.
It returns:
ModuleNotFoundError: No module named 'getdir'
Maybe not the most elegant but you can add the path in sys.path before importing getdir:
import sys
sys.path.append('..')
from getdir import somename #Now python will look for getdir in sys.path, including at '../'
Could you try (works for me):
from getdir.somename import classnameexample

How can I import a python module whose name is a uid?

For some reason, I had to change a module name from A.py to 0880ceae-8a46-11eb-bcf6-38f9d349be8e.py. 0880ceae-8a46-11eb-bcf6-38f9d349be8e.py is a uid generated by uuid.uuid1().
After my change, I try to import a class B from the py file by the following two ways, both do not work out.
First solution is to import directly
from 0880ceae-8a46-11eb-bcf6-38f9d349be8e import B
It has an error SyntaxError: invalid token
Second solution is to define a variable before import
uid = '0880ceae-8a46-11eb-bcf6-38f9d349be8e'
from uid import Model_API
And it has en error ModuleNotFoundError: No module named 'uid'
Anyone has a good idea? Thanks.
Here is possible solution to your problem tested using python3:
# Modern approach
import importlib
module = importlib.import_module(".", "0880ceae-8a46-11eb-bcf6-38f9d349be8e")
module.hello()
# Deprecated way
module = __import__("0880ceae-8a46-11eb-bcf6-38f9d349be8e")
module.hello()
Both of the above methods are tested and works.
Here are the rules to keep in mind:
Check your filename should end with .py extension, .py.py will cause ModuleNotFoundError.
Make sure to not include .py extension while using in importlib module.

"Global name not defined" error

There are several posts around this error I have already read, but I still don't get what I am doing wrong.
I put it into a minimal example:
Imagine I have a Doc.py, and the package Tools which includes Tool1.py and Tool2.py.
Doc.py:
from Tools import *
import sys
def __main__():
TOOL_REPORT("Tool1","Test")
def TOOL_REPORT(tool, path):
if(tool == 'Tool1'):
Tool1.REPORT(path)
elif(tool == 'Tool2'):
Tool2.REPORT(path)
else:
sys.stderr.write("This tool is not yet included in Doc. Please check TOOLS for more information.")
if __name__=="__main__": __main__()
Tool1.py:
def REPORT(path):
print("Tool1 "+path)
Tool2.py:
def REPORT(path):
print("Tool2 "+path)
If I run this, I always end up with this error:
File "Doc.py", line 15, in TOOL_REPORT
Tool1.REPORT(path)
NameError: global name 'Tool1' is not defined
I'd appreciate any hint to what is going wrong!
Your Tool1 and Tool2 submodules are not visible until explicitly imported somewhere.
You can import them in the Tools/__init__.py package file:
import Tool1, Tool2
at which point they become available for import from Tools.
Another option is to import the modules from your own code:
import Tools.Tool1, Tools.Tool2
from Tools import *
Only when explicitly imported are submodules also set as attributes of the package.
Python will treat any folder as a module when there is __init__.py file present in it. Otherwise it will just be another folder for python and not a module from which it can import things. So just add init.py file in your Tool folder (so it will become module in pythonic terms) and then you can import that module in other python scripts.
One more things for better practice instead of using
from Tools import *
Always provide the file name of library specifically which you want to import like in your case you should use it like this
from Tools import Tool1, Tool2
This will enhance the code readbility for others and for you too.

Python: Unit Testing Module and Relative Imports

Currently have the following file hierarchy:
\package
__init__.py
run_everything.py
\subpackage
__init__.py
work.py
work1.py
work2.py
\test
__init__.py
test_work.py
test_work1.py
My first question is regarding relative imports. Suppose in \subpackage\work.py I have a function called custom_function(), and I would like to test that function in test_work.py. For some reason I can not figure out how to make this import from one module to another. Trying from .. subpackage.work1 import custom_function() does not seem to work, and yields the error Attempted relative import in non-package Is there any way to resolve this?
2)
I would like to run all test files from run_everything.py with one function, would adding a suite() function in each test_work*.py file, which adds each unit_testing class to suite.addTest(unittest.makeSuite(TestClass)), and finally importing them into the top-level run_everything.py be the most conventional way in Python2.7?
Here is a hack*
Insert the path's to "subpackage" and "test" to your python path in run_everything using:
import sys
sys.path.insert(0, '/path/to/package/subpackage')
sys.path.insert(0, '/path/to/package/test')
And then, you can import all your files using vanilla imports in run_everything:
import work, work1, work2
import test_work, test_work1
*This won't permanently affect your PYTHONPATH.

Categories

Resources