Importing classes - Python - python

Good morning I am stuck with the following problem. Precisely, I have the following setup:
Project_Name
|
|--> __init__.py
|
|--> Tool1
| |
| |--> Object1.py
| |
| |--> __init__.py
|
|--> Tool2
|
|--> Object2.py
|
|--> __init__.py
where Project_name, Tool1 and Tool2 are folders. Object2 contains a class named 'House'. How can I use the class 'House' in Object1? I tried the following:
from Tool2.Object2 import House
but I receive error message 'No module named 'Tool2'.
What am I doing wrong? All init.py files are empty, should I change that?

1
If you are using VS code, the easiest fix is to start your script being executed like the following.
import sys
sys.path.append('/PATH/TO/Project_Name')
import Tool1.Object1
...
2
Or, you can add the environment variable PYTHONPATH to settings.json (can be found ctrl + shift + P then type settings.json)
"terminal.integrated.env.linux": {
"PYTHONPATH": "/PATH/TO/Project_Name/"
}
In this way, you can just
import Tool1.Object1
sys.path and PYTHONPATH will do the same for you.

You need to export PYTHONPATH to your Project_Name so that the interpreter knows the specific folder(s) to look up.
export PYTHONPATH=path/to/your/project
For example:
object1.py
from tool2.object2 import House
house = House()
house.print_message("Hello World!!!")
object2.py
class House(object):
def __init__(self):
pass
def print_message(self, text):
print(text)
Outputs before and after exporting PYTHONPATH
$ python tool1/object1.py
Traceback (most recent call last):
File "tool1/object1.py", line 2, in <module>
from tool2.object2 import House
ImportError: No module named tool2.object2
$ pwd
/Users/.../StackOverflow
$ export PYTHONPATH=/Users/.../StackOverflow
$ python tool1/object1.py
Hello World!!!
$ python object1.py
Hello World!!!

Related

A strange "No module named 'XX' " problem

I know how to import a package or module, but I meet a quite strange problem.
If I run swmm5_extend_function/example.py, everything is fine. However, when I run example.py, errors occur:
Traceback (most recent call last):
File "example.py", line 2, in <module>
from swmm5_extend_function.Swmm5Extend import SWMM5ReadInp
File "C:\project\swmm5_extend_function\Swmm5Extend.py", line 1, in <module>
import swig.SWMM5ReadInpFile as swmm
ModuleNotFoundError: No module named 'swig'
Here is my project structure:
project/
-- example.py
-- ......
-- swmm5_extend_function/
-- __init__.py
-- example.py
-- Swmm5Extend.py
-- swig/
-- __init__.py
-- SWMM5ReadInpFile.py
-- ....
Here is code of each .py file:
swmm5_extend_function/Swmm5Extend.py
import swig.SWMM5ReadInpFile as swmm
class SWMM5ReadInp(object):
pass
swmm5_extend_function/example.py
from Swmm5Extend import SWMM5ReadInp
example.py
from swmm5_extend_function.Swmm5Extend import SWMM5ReadInp
I want to know why this strange error happens.
For a better explanation, I've created the following folder structure:
test/
-- __init__.py
-- greeter.py # Greets in German
-- subfolder/
-- __init__.py
-- greeter.py # Greets in Italian
-- test.py
-- deepfolder/
-- __init__.py
-- greeter.py # Greets in France
As you may notice, we have 3 files with the same name, each one greets in a different language using a function with the same name. The only function in a greeter.py file is:
def says():
print("Hello World!")
IMPORT FROM THE SAME FOLDER
If from test.py file we import greeter and run the says function, we'll have:
import greeter as greeter
greeter.says()
Output:
Buongiorno Mondo! # Italian output
IMPORT FROM A SUBFOLDER
But what if we want to import from a subfolder?
To import from a subfolder (i.e., deepfolder/), we simply add an empty __init__.py file into the folder, then we can specify the path in the import:
import deepfolder.greeter as greeter
greeter.says()
Output:
Bonjour le Monde! # France output
IMPORT FROM A PARENT FOLDER
At last, you may want to import from a parent folder.
You should try to have your main running file at the top of the folder tree, but things happens and you find yourself looking to import a module from a parent folder.
For doing this, you need to add the parent folder to the sys.path:
import sys
sys.path.append("/path/to/dir")
from test import greeter as greeter
greeter.says()
Output:
Guten Morgen Welt! # German output
Importing scripts and modules isn't really the most pythonic way to solve things, you may want to have a look on Python's documentation about packages.
TL;DR
In your project/example.py use
import swmm5_extend_function.swig.SWMM5ReadInpFile as swmm
instead of
import swig.SWMM5ReadInpFile as swmm

Python - No module named but the module exist it

I have the next directory structure:
|-Server/
|-------OrderBook/
| |--------message.py
| |--------orderBookObject.py
|-------Rabbit/
| |--------emisor.py
| |--------receptor.py
|-------server.py
|-------processMessage.py
In server.py I have "from processMessage import A"
In processMessage.py I have "from OrderBook.orderBookObject import B"
and in orderBookObject.py I have "from Rabbit.emisor import C"
but I have the next error "ModuleNotFoundError: No module named 'Rabbit"
Why is this happening?
How can I fix it?
Edit:
If I move Rabbit folder inside OrderBook folder, I have the same error.
create a file named __init__.py inside directory OrderBook and Rabbit
this will create package, and then you can import
https://docs.python.org/3/tutorial/modules.html#packages
so your directory structure will be looked like :
|-Server/
|-------OrderBook/
| |--------__init__.py
| |--------message.py
| |--------orderBookObject.py
|-------Rabbit/
| |--------__init__.py
| |--------emisor.py
| |--------receptor.py
|-------server.py
|-------processMessage.py

Python Submodule is not getting imported

This is the file path for my Pydev project in Eclipse:
project
|
+----tests
| |
| +----subtests
| | |
| | +----__init__.py
| | |
| | +----test1.py
| |
| +----__init__.py
| |
| +----test2.py
|
+----mods
|
+----__init__.py
|
+----submods1
|
+----__init__.py
|
+----submods2
|
+----__init__.py
|
+----a.py
|
+----b.py
|
...
|
+----z.py
test1 and test2 are exactly the same, all of the init files only have comments in them. The tests are getting the modules from the mods directory and those modules dependencies. When I run test1, all of the modules are found, but test2 always unable to find the same module (let's call it "z.py") in submods2. But somehow it's able to find the rest of the modules. It's not that it's unable to import something in z.py, it just cannot find the file at all.
test2:
>>> from mods.submod1.submod2 import z
exec exp in global_vars, local_vars
File "<console>", line 1, in <module>
ImportError: cannot import name z
>>> from mods.submod1 import submod2
>>> hasattr(submod2, 'z')
False
The only difference in the sys.path during the two tests are the directories that tests are located in, project/tests/subtests for test1 and project/tests for test2.
I cannot figure out why test2 is unable to import z.py but test1 can and test2 can import the rest of the modules.
To help diagnose the issue, do:
from mods.submod1 import submod2
print(submod2)
My guess is that it's not the module you're expecting.
What Python version are you using?
I think I found my solution to this. In my Run Configurations for test2, the Working directory in the Arguments tab had a custom path ${workspace_loc:project/tests/}, I switched it to the default path ${project_loc:/selected project name} and that seems to be fixing the issue. While I don't understand how this fixed the problem, the result is good enough for me.

maya python call function from another py file

I have a python script saved to file.
test1.py
import maya.cmds as cmds
import sys
def process():
print 'working'
I need to run the function from this script inside another python script, inside maya. I have:
import sys
sys.path.append('J:\scripts\src\maya')
from test1 import process
test1.process()
but it gives me:
from test1 import process
# Error: ImportError: file <maya console> line 4: cannot import name process #
What am I doing wrong here?
('import test1' gives no error, so the path is correct).
Solution:
Reload your test1 module, my guess is that you created and imported test1 without the process method inside. To effectively reload a module, you can't just re-import it, you have to use the reload.
reload(test1)
from test1 import process
Other observations:
Use raw string when using paths:
Add r before your path string:
sys.path.append(r'J:\scripts\src\maya')
Python Doc
The backslash () character is used to escape characters that
otherwise have a special meaning, such as newline, backslash itself,
or the quote character. String literals may optionally be prefixed
with a letter 'r' or 'R'; such strings are called raw strings and use
different rules for interpreting backslash escape sequences.
Check the way you import your modules:
You wrote, which is not valid:
from test1 import process
test1.process()
But you can have either way:
import test1
test1.process()
or:
from test1 import process
process()
To sum-up these are the ways to import a module or package:
>>> import test_imports
>>> from test_imports import top_package
>>> from test_imports import top_module
test_imports.top_module
>>> from test_imports.top_package import sub_module
test_imports.top_package.sub_module
assuming you have the following hierarchy:
J:\scripts\src\maya # <-- you are here
.
`-- test_imports
|-- __init__.py
|-- top_package
| |-- __init__.py
| |-- sub_package
| | |-- __init__.py
| | `-- other_module.py
| |-- sub_module.py
`-- top_module.py
Credits goes to Sam & Max blog (French)
First you need to add the script location path in system path.
and if you are making this as a python package than do not forget to add
a __init__.py file in the package directory.
Than you can execute following code.
import sys
path = r'J:\scripts\src\maya'
if path not in sys.path:
sys.path.append(path)
import test1
test1.process()

List modules in namespace package

I'm trying to get Python to list all modules in a namespace package.
I have the following file structure:
cwd
|--a
| `--ns
| |--__init__.py
| `--amod.py
|--b
| `--ns
| |--__init__.py
| `--bmod.py
`--c
`--ns
|--__init__.py
`--cmod.py
Each __init__.py defines it's package as a namespace package by having the following line:
__import__('pkg_resources').declare_namespace(__name__)
The amod module contains a class A, bmod contains another class B and cmod contains the C class.
When having a clean environment the following happens:
>>> import inspect, sys, glob
>>> sys.path += glob.glob('*')
>>> import ns
>>> inspect.getmembers(ns, inspect.ismodule)
[]
As you can see, the modules are not listed.
Now when I import the modules manually and then call the inspect again:
>>> inspect.getmembers(ns, inspect.ismodule)
[('amod', <module 'ns.amod' from 'a/ns/amod.pyc'>), ('bmod', <module 'ns.bmod' from 'b/ns/bmod.pyc'>), ('cmod', <module 'ns.cmod' from 'c/ns/cmod.pyc'>)]
Now I'd like the inspect call to work without importing the modules manually, so how can I achieve this?

Categories

Resources