Imports not found when running script outside of Pycharm? - python-3.x

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

Related

gRPC generated code for Python 3 not working

protoc was generating invalid code in Python 3.8. I found that it works in Python 3.6.
I followed the instructions as per: This fantastic blog
The command I ran was:
python -m grpc_tools.protoc --python_out=src/ --grpc_python_out=src/ --proto_path generated=./src/interfaces src/interfaces/ecg.proto
The first issue was the generated imports were not working. I changed the code as below, for the import to work, in pb2_grpc.py:
from . import ecg_pb2 as generated_dot_ecg__pb2
The imports were fine in Visual Code, but now the run-time error.
I have a couple of files in the "generated" folder. I also added an init.py into this folder that was supposed to expose the contents, as:
from .ecg_pb2 import *
from .ecg_pb2_grpc import *
At a peer level to this "generated" folder I have another file - server.py. I am trying to import "generated". It is only importing with a relative path: from .generated import ecg_pb2_grpc
However, while the import works with the relative path, the main in server.py is not getting invoked. Run time error -
(p36) C:\ECG\src>python ecg_server.py
Traceback (most recent call last):
File "ecg_server.py", line 6, in
from .generated import ecg_pb2
ModuleNotFoundError: No module named 'main.generated'; 'main' is not a package

How to import from a module in the root directory?

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.

Import script in sub directory not working... Blender Add-On

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

How to make the path work to run tests outside of pytest

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

Skeleton Directory: Why does script fail when nosetests returns no errors?

(Using bash command line, Python 2.7.12 on Debian Linux.)
Following Zed Shaw's LPTHW, I built a project skeleton that helps with testing software. First, the outline.
The setup:
bin docs first_project setup.py tests
./bin:
./docs:
./first_project:
__init__.py wasp.py
./tests:
first_project_tests.py __init__.py
Contents of wasp.py:
def paint(color):
print color * 10
Contents of first_projects_tests.py:
from nose.tools import *
from first_project import wasp
def test_paint():
wasp.paint("blue")
Per my understanding of Zed Shaw's explanation, the __init__.py in the first_project directory tells Python that the files in it can be imported as modules. Thus the script first_project_tests.py in the test directory imports the wasp.py module from the first_project directory and calls the paint function from it.
Following Shaw's directions, I ran nosetests from above the tests directory and I got an ok with zero errors.
I then changed into the tests directory and typed python first_project_tests.py from the command line, assuming that I'd be able to run the script with no issues as the nosetests command gave no errors.
I got the following error:
Traceback (most recent call last):
File "first_project_tests.py", line 2, in <module>
from first_project import wasp
ImportError: No module named first_project
So why does the first_project_tests.py script fail when nosetests returns no errors?
Python imports work relative from the module search path. The current directory is automatically included on this path.
When you run the nosetests at the top level of your project, the first_project module with wasp inside is found at the relative path, since first_project/wasp.py exists relative from the execution directory.
When you go inside tests and try to run first_project_tests.py, the import statement fails because the relative path first_project/wasp.py doesn't exist from inside that directory.
You could run from the project root like this:
python tests/first_project_tests.py

Resources