I've installed two git submodules into my project. Those submodules contain a lot of relative imports, so if you just import something from them, they will not find necessary modules. This problem can be easily solved by adding following line before imports:
sys.path.insert(0, './yolov5_face') # where ./yolov5_face is path to submodule
But that solves problem only for one submodule.
I have following project structure:
/yolov5 # submodule
/yolov5_face # submodule
detect_face.py # script, which imports yolov5_face
track.py # script, which imports yolov5
Submodules are almost identical but have slightly different classes and functions. Script detect_face.py gets loaded first, so I insert './yolov5_face' to sys.path before imports from submodule. Then, in trace.py I insert './yolov5' before imports. So my sys.path after second insertion looks that way:
['./yolov5', './yolov5_face', '/home/sher/Dev/realtime-detection', ... ]
And I have following error:
File "/home/sher/Dev/realtime-detection/track.py", line 14, in <module>
from yolov5.models.common import DetectMultiBackend
File "/home/sher/Dev/realtime-detection/yolov5/models/common.py", line 23, in <module>
from utils.datasets import exif_transpose, letterbox
ImportError: cannot import name 'exif_transpose' from 'utils.datasets' (/home/sher/Dev/realtime-detection/./yolov5_face/utils/datasets.py)
Function exif_transpose resides in yolov5 submodule and its path appears first in sys.path, but it seems like python searches for this import in yolov5_face instead. yolov5_face contains utils.datasets module too, but does not have exif_transpose function. Also all imports from detect_face.py loads just fine.
Is there a way to resolve this problem and use two submodules together?
Related
I have three scripts:
C:\code\voiceTerm\master.py:
from voice_terminal_module.voice_terminal import VoiceTerminal
vterm = VoiceTerminal()
C:\code\voiceTerm\voice_terminal_module\voice_terminal.py:
from chatbot_module.chatbot_module import Chatbot
class VoiceTerminal:
print("INITIALIZING VOICE TERMINAL")
cb = Chatbot()
C:\code\voiceTerm\voice_terminal_module\chatbot_module\chatbot_module.py:
class Chatbot:
print("CHATBOT INITIALIZED")
Here is the wierd thing: When I run chatbot_module.py it works, and if I run voice_terminal.py it works. For some reason however, master.py errors out with the following message:
Traceback (most recent call last):
File "c:\code\voiceTerm\master.py", line 1, in <module>
from voice_terminal_module.voice_terminal import VoiceTerminal
File "c:\code\voiceTerm\voice_terminal_module\voice_terminal.py", line 1, in <module>
from chatbot_module.chatbot_module import Chatbot
ModuleNotFoundError: No module named 'chatbot_module'
Why does it work sometimes, but sometimes not?
You'll need to restructure your project in a way that you have either: (1) two separate and installed packages containing each module or; (2) one package containing all modules. The simplest way forward is (2) and it looks like:
master.py
src/ # Name it anything you wish
__init__.py
voice_terminal.py
chatbot_module.py
Then use relative imports in voice_terminal.py
from .chatbot_module import Chatbot
Rule: Packages does not know others exists unless the other package is installed, added to sys.path, a subpackage, or part of a parent package.
Python general importing guide (for your own code)
I'm sure there should be a duplicate for this by now, but I can't find it, so I'm writing a full essay.
To solve the problem properly, you must take care of two things:
Make sure that sys.path - the path that Python searches for modules - includes the path to the project root.
Make sure that the import statements in the code are written to work with that path.
The search path
For the first part, you must understand how sys.path works. It is a list of folders where Python will look, that is set up automatically at startup (even if you don't import sys - just like sys.argv is).
Normally, it will be a list which contains, in order:
A path to the entry point for execution (the details of this will depend on how Python is started; typically this is '' when running a .py file directly from the same directory, a path the another directory if you do e.g. python somewhere/else/file.py, and an explicit path when using the -m switch)
Paths to system libraries
Paths to virtual environment libraries, if a virtual environment is active
Paths to things that were explicitly installed by the user
You can modify this list, with the expected impact on future import statements; but you ordinarily should not.
To ensure your project root is on the path, normally you should just install the project - ideally into a virtual environment. Please see the Python packaging guide for details. Failing that, make sure to start the project from just outside the folder containing your "top-level" code. In OP's case, that means C:\code. This will ensure that C:\code (or something equivalent) is on sys.path, which we can then rely upon for the second step.
The imports
We can fundamentally do this in two ways: By absolute imports specifying the path from the root, or by relative imports specifying the path from the current source file. Read more on Stack Overflow about relative imports here and here.
Absolute imports
In either case, we want to treat the root folder for our project (here, C:\code\voiceTerm) as a package. For absolute imports, this means we will always mention the root folder name in our import path.
Thus:
In C:\code\voiceTerm\master.py: from voiceTerm.voice_terminal_module.voice_terminal import VoiceTerminal
In C:\code\voiceTerm\voice_terminal_module\voice_terminal.py: from voiceTerm.voice_terminal_module.chatbot_module.chatbot_module import Chatbot
(You don't really want to have _module in your folder or file names. It doesn't really add information, makes this considerably harder to type, and is actually a bit misleading.)
We can also import entire modules: import voiceTerm.master, import voiceTerm.voice_terminal_module.voice_terminal; import voiceTerm.voice_terminal_module.chatbot_module.chatbot_module. Additionally, by naming a file __init__.py, we become able to import the folder as a package: import voiceTerm; import voiceTerm.voice_terminal_module; import voiceTerm.voice_terminal_module.chatbot_module. We can also import a module from one of those packages: from voiceTerm import master; from voiceTerm.voice_terminal_module import voice_terminal; from voiceTerm.voice_terminal_module.chatbot_module import chatbot_module.
Relative imports
With relative imports, we must use the from syntax, and we can only import things from within our own package hierarchy. However, we have the advantage that we don't have to specify full paths, and we can rename packages without having to edit the code. My personal recommendation is to use relative imports where possible; this also makes a strong visual distinction with imports from system libraries or other third-party packages.
For a relative import, first we specify the package or sub-package that we're importing from, using a relative import path. By starting with a single ., we start from the current directory, looking for another module or package within the same folder.
Thus:
In C:\code\voiceTerm\master.py: from .voice_terminal_module.voice_terminal import VoiceTerminal to import the class; from .voice_terminal_module import voice_terminal to import the module.
In C:\code\voiceTerm\voice_terminal_module\voice_terminal.py: from .chatbot_module.chatbot_module import Chatbot to import the class; from .chatbot_module import chatbot_module to import the module.
Additional .s navigate up the package hierarchy (but we cannot go beyond the root this way). For example, from ... import master to import the top-level master.py from the lower-down chatbot_module.py. (Of course, this wouldn't actually work in this case, because it would be a circular import.) To import another source file (as a module) from the same directory, simply from . import other_file. You get the idea.
I solved it. You can appearantly use importlib for this. I replaced the import code in my voice_terminal.py script with this:
chatbot_module = SourceFileLoader("chatbot_module", "C:/code/voiceTerm/voice_terminal_module/chatbot_module/chatbot_module.py").load_module()
I'm having trouble with a python package that uses separate modules to structure code. The package itself is working, however when imported from another environment fails with a ModuleNotFound error.
Here's the structure:
Project-root
|
|--src/
| __init__.py
| module_a.py
| module_b.py
| module_c.py
| module_d.py
|--tests
etc.
In module_a.py I have:
from module_a import function_a1,...
from module_b import function_b1,...
from module_c import function_c1,...
In module_c I import module_d like:
from module_d import function_d1,...
As mentioned above, executing module_a or module_c directly from the CLI work as expected, the unit tests I've created in the test directory also work (with the help of sys.path.insert), however if I create a new environment and import the package I get the following error:
>>> import module_a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/<abs_path>/.venv/lib/python3.9/site-packages/module_a.py", line 22, in <module>
from module_c import function_c1, function_c2
File /<abs_path>/.venv/lib/python3.9/site-packages/module_c.py", line 9, in <module>
import module_d
ModuleNotFoundError: No module named 'module_d'
>>>
I've exhausted all ideas how to overcome this, besides combining the code of modules c and d in one file, which I'd hate to do, or rethink the flow so that all modules are imported from module_a.
Any suggestions how to approach this would be greatly appreciated.
Update: It turned out to be a typing mistake in the name of module_d in setup.py. For whatever reason python setup.py install was failing silently or I wasn't reading the logs carefully.
The problem comes down to understanding the basics of the import system and the PYTHONPATH.
When you try to import a module (import module_a), Python will search in order in every directory listed in sys.path. If a directory matches the name (module_a)1, then it runs the __init__.py file is such exist.
When you get an [https://docs.python.org/3/library/exceptions.html#ImportError], it means that there is no directory in sys.path containing a directory with the name asked.
You said for your tests you did something like sys.path.insert(0, "some/path/"), but it is not a solution, just a broken fix.
What you should do is set your PYTHONPATH environment variable to contain the directory where your modules are located, Project-root/src in your case. That way, no need to ever use sys.path.insert, or fiddle with relative/absolute paths in import statements.
When you create your new environment, just set your environment variable PYTHONPATH to include Project-root/src and you are done. This is how installing regular Python modules (libraries) work : they are all put into a directory in site-packages.
1: this changed since old Python versions, it used to be required for the directory to contain an __init__.py file
I know this question has been asked before but I couldn't get to an answer.
My package folder looks like this, no sub folders, just a flat package folder with .py files in it.
+Package
∣
∣--__init__.py
∣--moduleA.py
∣--moduleB.py
If I run my test.py script from inside the package folder, the imports, classes and methods work fine:
import moduleA.py
import moduleB.py
# ...stuff
Now, if I try to run my package from outside importing import Package, outside being \site-packages I get
File "defaultPathTo\Python\Python38\lib\site-packages\Package\__init__.py", line 1, in <module>
import moduleA
ModuleNotFoundError: No module named 'moduleA'
This is my init file
import moduleA
import moduleB
I tried changing the content to from moduleA import *, from . import moduleA
from .moduleA import (whatever class) seems to work, but I don't want to change all my classes from moduleA.ClassA because it clashes with class names from the other modules.
I think I summed up all the information neede. Thanks for the help
Using from . import moduleA for all imports from within my package did the trick.
I may have done something wrong the first time I tried because I got no known parent folder
I am trying to run a program, whose files are organized as follows, The subfolder of tensorflow_fcn and architecture.py share the same parent directory. In architecture.py, there is a line of code from tensorflow_fcn import fcn8_vgg
The folder of tensorflow_fcn already includes _init_.py
However, running the program gets error message as follows
File "FCN/KittiSeg_pretrained/model_files/architecture.py", line 5, in <module>
from tensorflow_fcn import fcn8_vgg
ImportError: No module named 'tensorflow_fcn'
I do not understand why tensorflow_fcn was not identified by architecture.py.
.../model_files is probably not in your PYTHON_PATH. In Python 3 you can use relative imports for this:
from .tensorflow_fcn import fcn8_vgg
Note the . .
This may also work in 2.7, although you should definitely upgrade if you're still using 2.7 .
Maybe this is related to the relative path of the file and module.
In my work, there is a subfolder "submodules" at the same level as the file, while subfolder "tensorflow_fcn" is under "submodules". So I use this form:
from submodules.tensorflow_fcn import fcn8_vgg
This page may solve your puzzle
http://85608547.blog.51cto.com/2093443/1576759
In a module residing inside a package, i have the need to use a function defined within the __init__.py of that package. how can i import the package within the module that resides within the package, so i can use that function?
Importing __init__ inside the module will not import the package, but instead a module named __init__, leading to two copies of things with different names...
Is there a pythonic way to do this?
Also, starting in Python 2.5, relative imports are possible. e.g.:
from . import foo
Quoting from http://docs.python.org/tutorial/modules.html#intra-package-references:
Starting with Python 2.5, in addition to the implicit relative imports described above, you can write explicit relative imports with the from module import name form of import statement. These explicit relative imports use leading dots to indicate the current and parent packages involved in the relative import. From the surrounding module for example, you might use:
from . import echo
from .. import formats
from ..filters import equalizer
This doesn't exactly answer your question, but I'm going to suggest that you move the function outside of the __init__.py file, and into another module inside that package. You can then easily import that function into your other module. If you want, you can have an import statement in the __init__.py file that will import that function (when the package is imported) as well.
If the package is named testmod and your init file is therefore testmod/__init__.py and your module within the package is submod.py then from within submod.py file, you should just be able to say import testmod and use whatever you want that's defined in testmod.
I'm not totally sure what the situation is, but this may solve your "different name" problem:
import __init__ as top
top.some_function()
Or maybe?:
from __init__ import some_function
some_function()
In Django, the file manage.py has from django.core.management import execute_manager, but execute_manager is not a module. It is a function within the __init__.py module of the management directory.