Issue
I'm having a hard time trying to separate some utility code as a module. I have the the following file structure:
scripts/
|
+-- toggle_keyboard.py
PyUtils/
|
+-- sistema.py
+-- strings.py
+-- test_sistema.py
Sistema.py needs a class in strings.py, so it begins with:
from strings import String
And the Pytest test_sistema.py needs sistema.py, so it starts with:
import sistema as sis
Now, this is all fine when I run the tests with PyTest. However, I can't use this module in toggle_keyboard.py. I start it with:
import PyUtils.sistema as sis
And that gets me no compilation errors. However, when I run it, this is what I get:
Traceback (most recent call last):
File "toggle_keyboard.py", line 2, in <module>
import PyUtils.sistema as sis
File "/home/xxxxxx/scripts/PyUtils/sistema.py", line 2, in <module>
from strings import String
ModuleNotFoundError: No module named 'strings'
Searching for similar problems online, I found that making use of "relative imports" could solve the problem. Indeed, I was able to run toggle_keyboard.py when I changed sistema.py with this:
from .strings import String
However, the test doesn't run anymore. When I execute PyTest now, I get:
Traceback:
/usr/lib/python3.6/importlib/__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
PyUtils/test_sistema.py:1: in <module>
import sistema as sis
PyUtils/sistema.py:2: in <module>
from .strings import String
E ImportError: attempted relative import with no known parent package
What would be a solution to make both the main script and the module's test to work?
Solution
In your sistema.py
file try:
from PyUtils.strings import String
and in test_sistema.py
import PyUtils.sistema as sis
and ensure your PyUtils
directory contains an __init__.py
file and that should fix the issue.
An alternative approach although one that is typically not recommended:
Add the top 3 lines from below in any file in the scripts
dir that imports from the PyUtils
dir.
toggle_keyboard.py
import sys
from pathlib import Path
sys.path.insert(0, Path(__file__).parent / "PyUtils")
from PyUtils.systema as sis
from PyUtils.strings import String
...
then the files in PyUtils
can go back to:
from strings import String
import sistema as sis
You would still want to have the __init__.py
in PyUtils
dir.
And another approach would be to catch exceptions on the imports and try alternatives like so....
sistema.py
try:
from strings import String
except ImportError:
from PyUtils.strings import String
test_sistema.py
try:
import sistema.py as sis
except ImportError:
import PyUtils.sistema as sis
This is actually the better option in your situation.
Answered By - alexpdev
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.