I have the following project structure:
root
|--pkg1
| |--__init__.py
| |--other_stuff.py
|--stuff.py
In the real project, I also have a tests package in the root directory.
If I run unit tests with python -m unittest at root, it works seamlessly.
I want to make the other_stuff.py module also executable as a script.
However, if I run it from either root or pkg1 directories, the Python interpreter returns me this error:
Traceback (most recent call last):
File "pkg1/other_stuff.py", line 1, in <module>
from stuff import Dummy
ModuleNotFoundError: No module named 'stuff'
Here is the code:
# file pkg1/__init__.py
# (empty)
# file pkg1/other_stuff.py
from stuff import Dummy
if __name__ == '__main__':
# do other stuff
pass
# file stuff.py
class Dummy:
pass
I also tried the package relative imports from .stuff and from ..stuff, but it gives the error:
Traceback (most recent call last):
File "pkg1/other_stuff.py", line 1, in <module>
from ..stuff import Dummy
ImportError: attempted relative import with no known parent package
I'm not used to the Python3 import system.
What is the right way to import stuff.py in other_stuff.py to make it work both in the tests and as a script?
I have found a solution that might not be the best, but it worked.
To run other_stuff.py as a script, I just need to open the terminal in the root directory and run python3 -m pkg1.other_stuff.
Related
I'm using Python 3.10.
I have the following directory:
folder project
The File parse-subfinder.py , has a code:
parse-subfinder
But I get the error:
Traceback (most recent call last):
File "c:\Users\Windows\Desktop\smart-recon\subdomains\parse-subfinder.py", line 2, in
from ..utils.directory import Directory
ImportError: attempted relative import with no known parent package
How can I make this work?
I tried:
from ..utils.directory import Directory
from ..utils.discover import Discover
I have a folder structure like this:
C:
|_Blueprint
│ main.py
│
└───toolbox
blueprint_tools.py
When I run this code in Blender's scripting text page:
from toolbox.blueprint_tools import dimension, array, modify
I get an error in the console
Traceback (most recent call last):
File "\main.py", line 20, in <module>
ModuleNotFoundError: No module named 'toolbox'
Error: Python script failed, check the message in the system console
I swear, when I run this code (on other projects) outside of Blender this structure and code runs fine. But I get an error when running this script in Blender for testing out my Add-On.
If I compile the Blueprint folder into a .zip and install it everything works fine.... ??
I'm lost, could anyone please help me.
If I run the code like this: (added a . before toolbox for CWD)
from .toolbox.blueprint_tools import dimension, array, modify
Traceback (most recent call last):
File "\main.py", line 20, in <module>
ImportError: attempted relative import with no known parent package
Error: Python script failed, check the message in the system console
Both your error traces write File \main.py ... which means that Blender considers your main.py file to be in the root folder, knowing nothing about its real location in the file system hierarchy.
When you installed your structure as a zip file, you provided all necessary info to Blender.
Addendum:
Temporarily, during developing / debugging your add-on, you may add the full path (for finding your toolbox.blueprint_tools module) to the sys.path variable.
There are 2 possibilities how to do it:
Insert into your main.py file these commands (use the path to your parent folder of your toolbox folder, of course):
import sys
sys.path += [r"C:\Users\Davi\Documents\Python\PARENT_of_toolbox"]
before your statement
from toolbox.blueprint_tools import dimension, array, modify
command, or
Insert into your main.py file these commands (use the path to your toolbox folder, of course):
import sys
sys.path += [r"C:\Users\Davi\Documents\Python\PARENT_of_toolbox\toolbox"]
before your modified statement
from blueprint_tools import dimension, array, modify
I have a test that passes with pytest. I also have an adjacent source that's a console app (not pytest) that exercises the same function that barfs with ModuleNotFoundError for the same function call.
mylib/mylib.py:
def adder(num1, num2):
return num1 + num2
test/my_test.py:
from mylib.mylib import adder
def test_adder():
assert adder(2, 2) == 4
test/mytest_outside_pytest.py:
from mylib.mylib import adder
print(str(adder(2, 2)))
As I suggest pytest completes and indicates the test passed, but the following does not:
$ python3 test/mytest_outside_pytest.py
Traceback (most recent call last):
File "test/mytest_outside_pytest.py", line 1, in <module>
from mylib.mylib import adder
ModuleNotFoundError: No module named 'mylib'
Nor does:
$ cd test/
$ python3 mytest_outside_pytest.py
Traceback (most recent call last):
File "mytest_outside_pytest.py", line 1, in <module>
from mylib.mylib import adder
ModuleNotFoundError: No module named 'mylib'
I have empty __init__.py in both folders. I don't know what pytest does to path loading that I can't replicate in my "main" console app. Of course I don't really care about an adder lib, I'm just aiming at the smallest reproducible problem.
pytest has a quite complex mechanism to add some directories to the PYTHONPATH and allow tests to run automagically (see the doc)
When you do not use pytest you do not have this mechanism and you have to manage the PYTHONPATH by yourself.
Why the PYTHONPATH is not correct in your case?
When you run a module using python path/to/module.py, the interpreter adds the directory containing the module (absolute path of path/to in this example) in the PYTHONPATH.
In your case, you run python test/mytest_outside_pytest.pyand the interpreter adds the absolute path of test directory in the PYTHONPATH.
You can check it by adding import pdb; pdb.set_trace() at the very beginning of your mytest_outside_pytest.py module to enter a debug session and run it. Then import sys and display the sys.path to see that test is the first directory in your PYTHONPATH.
You can also see that the root directory is not listed and thus the packages it contains cannot be imported.
How to solve it?
It can be done in multiple ways.
You can manually define the PYTHONPATH in your command:
PYTHONPATH=. python test/mytest_outside_pytest.py
or you can use python -m ... as suggested in comment (do not forget that in this case, you have to specify a module, not a path, and remember that it will work only from the directory containng the mylib and test packages):
python -m test.mytest_outside_pytest
In both cases, a debug session can show you that the root directory and the test directory are in the PYTHONPATH
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.)
I have a project structured this way...
main.py imports scripts from subfolders like so:
from controllers.available_balances_controller import available_balances_controller
Subfolders:
models
views
controllers
When running main.py in Pycharm it works find.
When I try to run in terminal I get import errors:
Traceback (most recent call last):
File "main.py", line 6, in <module>
from controllers.available_balances_controller import available_balances_controller
ImportError: No module named controllers.available_balances_controller
Am I importing the scripts wrong in main.py?
What is the proper way to do the importing?
Try running your script with the -m flag:
$ python -m main
That means that you are running your main.py as a module inside a python package, not as a simple script. PyCharm makes it easy for you by assuming so when you create a project. When you are in the terminal, you need to specify it yourself. You don't need __init__.py files inside your directories in Python3.
Check out:
https://docs.python.org/3/reference/import.html
Relative imports in Python 3