relative import with `__package__` specified - python

I know there are hundreds of post on this issue, but as fare as I see, mine is a bit different.
My project structure is the following:
package/
>script.py
>__init__.py
>submodule
>__init__.py
>otherstuff.py
>...
You should be able to run script.py simpy as a script $ ./package/script.py.
script.py needs information of submodule.__init__ so i attempt do do a relative import of submodule.
According to PEP-366 it is not possible to do relative imports, because if the script is run, __name__ will be set to '__main__' and __package__ to None.
To still use relative imports I manually set __package__ = 'package' before my imports. This allows me to properly do import package.
However from . import plotter yields
Traceback (most recent call last):
File "./script.py", line 9, in <module>
import package
File ".../package/script.py", line 13, in <module>
from . import submodule
ImportError: cannot import name submodule
if I previously imported package.
Else it yields
Traceback (most recent call last):
File "./script.py", line 12, in <module>
from . import submodule
SystemError: Parent module 'package' not loaded, cannot perform relative import
Can anyone help me how to fix the relative imports?
I don't want to use path hacks like
from os import path, pardir
from sys import path as syspath
PATH = path.abspath(path.dirname(__file__))
syspath.append(path.join(PATH, pardir))
and it is also not possible to add package to the path.

Related

Python Import Error: I am getting error when importing function from package. Import error on test.py when performing mymath.multiply()

This is my Directory Structure:
test.py
mymath/
__init__.py
mymath.py
test.py
import mymath
mymath.multiply()
__init__.py
from mymath
import multiply
mymath.py
def multiply():
When I run:
python3 test.py
I get the error:
Traceback (most recent call last):
File "test.py", line 2, in <module>
import mymath
File "/home/kcb/python-scripts/mymath/__init__.py", line 1, in <module>
from mymath import multiply
ImportError: cannot import name 'multiply'
When you run python myscript.py, the current working directory directory is added to your module search path, and thus any modules in that directory are importable.
However, when mymath/__init__.py tries to do from mymath import multiply, it can't find mymath.py, because mymath/ is not in your module search path.
The best solution is to change mymath/__init__.py to use a different import statement:
from .mymath import multiply
This means "import multiply from a module named mymath in the same directory as this module."

Import file from one directory up

I am working to import a file from one directory up.
Fitv/
__init__.py
BrowserPool.py
FitvTests/
__init__.py
environment.py
So with the above file structure, I want to import BrowserPool into environment.
I started with:
from Fitv.BrowserPool import BrowserPool
And got this:
File "..\environment.py", line 4, in <module>
from Fitv.BrowserPool import BrowserPool
ModuleNotFoundError: No module named 'Fitv'
Looking at various sources I tried:
from .. import BrowserPool
I got this:
File "..\environment.py", line 3, in <module>
from .. import BrowserPool
KeyError: "'__name__' not in globals"
Tried (used absolute path):
import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath('D:/Dev/Python/Fitv-master-new/Fitv/'))))
from Fitv.BrowserPool import BrowserPool
Got:
File "..\environment.py", line 3, in <module>
from Fitv.BrowserPool import BrowserPool
ModuleNotFoundError: No module named 'Fitv'
Tried (used relative path):
import sys
sys.path.append('/Fitv-master-new/Fitv/')
from Fitv import BrowserPool
Got:
File "..\environment.py", line 8, in <module>
from Fitv import BrowserPool
ModuleNotFoundError: No module named 'Fitv'
What am I doing wrong and how do I fix it?
Imports in Python are always relative to the path that the Python interpreter runs from, and from the path to environment.py shown in your trackback that includes a ..:
File "..\environment.py", line 8, in <module>
it is apparent that you are running environment.py from a sub-directory under the FitvTests, rather than the same directory where environment.py is located, in which case the .. in your import statement would simply refer to the FitvTests directory rather than its parent directory, Fitv.
You should either run environment.py from the FitvTests directory, or if you have a good reason to run it from the sub-directory you currently run it from, use ... instead to refer to the directory 2 levels up:
from ...BrowserPool import BrowserPool

Python nested subpackage doesn't import when running tests

I have a folder structure like this:
api
-- test
-- test_api.py
-- __init__.py
-- api
-- api.py
-- __init__.py
-- sub
-- sub.py
-- __init__.py
sub.py:
Base = 'base'
api.py:
from sub.sub import Base
def stuff_to_test():
pass
test_api.py:
from api.api import stuff_to_test
def test_stuff_to_test():
stuff_to_test()
I am in directory api.
I run pytest:
==================================== ERRORS ====================================
______________________ ERROR collecting tests/test_api.py ______________________
ImportError while importing test module '/<somepath>/api/tests/test_api.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_api.py:1: in <module>
from ..api.api import stuff_to_test
api/__init__.py:1: in <module>
from . import api
api/api.py:1: in <module>
from sub.sub import Base
E ImportError: No module named 'sub'
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.08 seconds ============================
Same happens if I run the python interpreter and import stuff from test_api.py:
>>> from tests.test_api import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/<somepath>/api/tests/test_api.py", line 1, in <module>
from api.api import stuff_to_test
File "/<somepath>/api/api/__init__.py", line 1, in <module>
from . import api
File "/<somepath>/api/api/api.py", line 1, in <module>
from sub.sub import Base
ImportError: No module named 'sub'
My first idea was to make the import in api.py relative:
from .sub.sub import Base
This way tests run fine.
But if I run python api/api.py I get this error:
Traceback (most recent call last):
File "api/api.py", line 1, in <module>
from .sub.sub import Base
SystemError: Parent module '' not loaded, cannot perform relative import
How can I have it so tests run and application runs?
I solved it by adding the following to test.__init__.py
project_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
api_path= os.path.join(project_path, 'api')
sys.path.append(api_path)
In python there are two ways to import a module, with a relative path or with an absolute path.
When you write from sub.sub import Base you are doing an absolute path import, for a relative path import write from .sub.sub import Base.
An absolute path import go look in the PYTHONPATH to find the starting point of your import, so you should write from api.sub.sub import Base.
For more information: Absolute vs. explicit relative import of Python module

regarding using sys.path.insert and import multiple path information contained in a folder

In demo.py of this project, there is one line of code sys.path.insert(1, 'incl'). After running this line of code, we can see that sys.path has added one more extra item 'incl'. As shown from the github project, we can see there is a subfolder named as 'incl' containing some path information. I can guess that with the help of sys.path.insert, we should be able to include these path information, but running from seg_utils import seg_utils as seg fails by giving the error message of. My estimation is that 'incl' was not correctly imported into sys.path.
Traceback (most recent call last):
File "demo.py", line 52, in <module>
from seg_utils import seg_utils as seg
ImportError: No module named seg_utils

my pythonpath has 'register2',why i can't import it

import sys
print sys.path
['D:\\zjm_code\\register2', 'C:\\WINDOWS\\system32\\python25.zip', 'D:\\Python25\\DLLs', 'D:\\Python25\\lib', 'D:\\Python25\\lib\\plat-win', 'D:\\Python25\\lib\\lib-tk', 'D:\\Python25', 'D:\\Python25\\lib\\site-packages']
and
#from django.core.management import setup_environ
from register2 import settings
#setup_environ(settings)
Traceback (most recent call last):
File "D:\zjm_code\register2\b.py", line 4, in <module>
from register2 import settings
ImportError: No module named register2
why ,
thanks
When directory 'D:\\zjm_code\\register2' is on sys.path, this means you can import modules and packages that are INSIDE that directory.
To import the directory register2 itself, two conditions:
its parent, 'D:\\zjm_code', must be on sys.path; and
file 'D:\\zjm_code\\register2\\__init__.py' must exist
__init__.py is the code that actually executes when you "import the directory".
lol because it tries to import something from register2 but it cannot since there isn't D:\zjm_code on the path..

Categories

Resources