I have a directory in my Python 3.3 project called /models.
from my main.py I simply do a
from models import *
in my __init__.py:
__all__ = ["Engine","EngineModule","Finding","Mapping","Rule","RuleSet"]
from models.engine import Engine,EngineModule
from models.finding import Finding
from models.mapping import Mapping
from models.rule import Rule
from models.ruleset import RuleSet
This works great from my application.
I have a model that depends on another model, such that in my engine.py I need to import finding.py in engine.py. When I do: from finding import Finding
I get the error No Such Module exists.
How can I import class B from file A in the same module/directory?
Since you are using Python 3, which disallows these relative imports (it can lead to confusion between modules of the same name in different packages).
Use either:
from models import finding
or
import models.finding
or, probably best:
from . import finding # The . means "from the same directory as this module"
Apparently I can do: from .finding import Finding and this works.
And the answer below reflects this as well so I guess this is reasonably correct.
I've fixed up my file naming and moved my tests to a different directory and I am running smoothly now. Thanks!
Related
i'm struggling with something that feels like it should be simple.
my current dir looks like this:
root/
└─ __init__.py (tried with it and without)
└─ file_with_class.py
└─ tests_folder/
└─ __init__.py (tried with it and without)
└─ unittest_for_class.py
unittest_for_class.py needs to import the class from file_with_class to test it, i tried to import it in various ways i found online but i just keep getting errors like:
(class name is same as file name lets say its called file_with_class)
File "tests_folder/unittest_for_class.py", line 3, in <module>
from ..file_with_class import file_with_class
ValueError: Attempted relative import in non-package
File "tests_folder/unittest_for_class.py", line 3, in <module>
from file_with_class import file_with_class
ImportError: No module named file_with_class
and others..
what is the correct way to import a class from a .py file that is in the parent folder ?
As a short explanation
import * from ..parent works if your program started at the parent level.
You import submodules which can have cross relations to other submodules or files in the package -> They are only relative inside a package not the os structure.
Option 1
you actually enter via a script in your parent folder and import your mentioned file as a submodule. Nicest, cleanest and intended way, but then your file is no standalone.
Option 2 - Add the parent dictionary to your path
sys.path.append('/path/to/parent')
import parent
This is a little bit dirty as you now have an extra path for your imports but still one of most easiest ones without much trickery.
Further Options and theory
There are quite a few posts here covering this topic relative imports covers quite a few good definitions and concepts in the answers.
Option 3 - Deprecated and not future proof importlib.find_loader
import os
import importlib
current = os.getcwd() # for rollback
os.chdir("..") # change to arbitrary path
loader = importlib.find_loader("parent") # load filename
assert loader
parent = loader.load_module() # now this is your module
assert parent
os.chdir(current) # change back to working dictionary
(Half of an) Option 4
When working with an IDE this might work, Spyder allows the following code. Standard python console does NOT.
import os
current = os.getcwd()
os.chdir("..")
import parent
os.chdir(current)
Following up on #Daraan's answer:
You import submodules which can have cross relations to other submodules or files in the package -> They are only relative inside a package not the os structure.
I've written an experimental, new import library: ultraimport which allows to do just that, relative imports from anywhere in the file system. It will give you more control over your imports.
You could then write in your unittest_for_class.py:
import ultraimport
MyClass = ultraimport("__dir__/../file_with_class.py", "MyClass")
# or to import the whole module
file_with_class = ultraimport("__dir__/../file_with_class.py")
The advantage is that this will always work, independent of sys.path, no matter how you run your script and all the other things that were mentioned.
You can add the parent folder to the search path with sys.path.append() like so:
import sys
sys.path.append('/path/to/parentdir')
from file_with_class import file_with_class
...
See also the tutorial for how Python modules and packages are handled
Just keep from file_with_class import file_with_class. Then run python -m test_folder.unittest_for_class. This supports running the script as if it is a module.
I have python code that is structured like this:
src
--->commoncode.py
--->folder1
--->file1.py
--->folder2
--->file2.py
--->folder3
--->file3.py
I want to use the code that is in commoncode.py in the files fileN.py. I have tried includingfrom . import commoncode but that does not work (ImportError: cannot import name 'commoncode').
I am able to use the code with import commoncode if I include a symlink in each of the subfolders but that seems hacky and sort of defeats the purpose of having common code.
The only code in commoncode.py right now is class commoncode():.
Let me know if there is any information that I can further provide that would be useful.
Since you're not using packages, one way is to modify your path:
import sys
sys.path.insert(0, "..")
from commoncode import <whatever>
# Now you can access imported symbols from commoncode.py
usually when importing you need to import as follows,
from (Name of the module) import (name of the class within the module).
so in your case, if I understood correctly I believe it would be:
from (Name of the common code module) import commoncode.
at the top of any of your modules you wish to use commoncode in, this is how it would be imported.
Please make sure that you haven't missed any capital or lowercase letters as well, as it is case sensitive when you import. Hope this could be of some help.
I want to import main_file.py from sub_file.py, i have my init files setup. I am able to do in my main_file.py:
from sub_folder.sub_file import *
However i do not know how to do it the other way around.
This is my structure:
|+main_folder
|--_init_.py
|--main_file.py
|++sub_folder
|---_init_.py
|---sub_file.py
The old way:
Make sure the directory with main_folder is on your sys.path;
from main_folder import main_file.
The new, usually better way:
from ..main_folder import main_file
This has the advantage of never clashing with system imports. If you rename your main_folder to e.g. math, from math import my_func will crash, because stdlib's math does not have this function, or import from your module, depending on sys.path. OTOH from ..math import my_func will definitely always import from your own module.
If in doubt, always print sys.path before your failing import statement to understand if you're actually looking at the right directories.
I am having a simple directory structure, like that:
MyProject
--main.py
--lib #that's a directory/package
----__init__.py
----view.py
----common_lib.py
----other irrelevant modules...
In main.py:
from lib import view
causes the following error:
ImportError: cannot import name view
If instead, I write it like:
from lib.view import *
This import passes successfully, but next failure happens in view.py, in that:
from common_lib import Comments, Locations, ScreenData, ProgressSignal
causes:
ImportError: No module named 'common_lib'
And as it appears from the directory structure, common_lib.py resides in the same directory as view.py, how can it happen that it cannot be found?
How does it come that 'from x import y' doesn't work, and 'from x.y import *' works?
'__init__.py' is completely empty BTW. And I am using Python 3.3 32-bit.
What is more annoying, this same program worked 2 days ago.I was testing some code in IDLE and when I thought the code was ready to include in the project, pasted it into PyDev, I was shocked by this error. I changed nothing about my directories or modules.
Also, still more strangeness, running view.py and common_lib.py as standalone (without being imported) runs just fine. It should produce the error if any issues really existed.
Thanks. Any advice is highly appreciated.
Since main.py is still at the top level, you need to use lib.common_lib:
from lib.common_lib import Comments, Locations, ScreenData, ProgressSignal
because the previous line from lib import view does not start looking for modules from inside lib.
Given:
+--main.py # from lib import view
+--lib
+--__init__.py
+--common_lib.py # Comments, etc.
+--view.py # from .common_lib import Comments, etc.
This works:
from lib import view
And this works from view.py with a relative import to indicate common_lib is in the same package.
from .common_lib import Comments, Locations, ScreenData, ProgressSignal
Works for me:
danielallan#MacBook:~$mkdir myproject
danielallan#MacBook:~$cd myproject/
danielallan#MacBook:myproject$mkdir lib
danielallan#MacBook:myproject$cd lib
danielallan#MacBook:lib$touch __init__.py
danielallan#MacBook:lib$touch view.py
danielallan#MacBook:lib$touch common_lib.py
danielallan#MacBook:lib$cd ..
In [1]: from lib import view
In [2]: view
Out[2]: <module 'lib.view' from 'lib/view.pyc'>
What happens when you try that on your machine? Are you sitting in the wrong directory, or is your path not configured to find these files?
Let's say I have such a directory structure:
- Documents/
- thesis_program/
- __init__.py
- classes.py
- utils.py
- GE_Test.py
- GE_Test_fail.py
classes.py and utils.py contains some classes and functions.
GE_Test.py and GE_Test_fail.py contains the exactly same code, except the import part.
In GE_Test.py I import classes and utils this way:
from utils import execute
from classes import Grammatical_Evolution
While in GE_Test_fail.py, I import classes and utils this way:
from thesis_program.utils import execute
from thesis_program.classes import Grammatical_Evolution
And unexpectedly I get a different result. Is there anything wrong here?
Do I import the modules correctly?
I can ensure that the result should be the same, because I generate the random number with certain seed
Also classes.py is somehow depended on utils.py since I have several common functions in utils.py. I suspect that utils is also a name used by the system. So in the second case (GE_Test_fail.py) The system utils override my utils.py. But it doesn't seem make sense for me.
The complete source code of classes.py and utils.py is available here (if it helps to discover what's wrong): https://github.com/goFrendiAsgard/feature-extractor
And also, the screenshots: https://picasaweb.google.com/111207164087437537257/November25201204?authuser=0&authkey=Gv1sRgCOKxot2a2fTtlAE&feat=directlink
add below mentioned lines to your test files which are going outside of your thesis folder.
import sys sys.path.insert(0,"/path to your thesis folder/thesis_program")
and maintain everything else; for example in GE_Test.py.. .
import sys
sys.path.insert(0,"/path to your thesis folder/thesis_program")
from utils import execute
from classes import Grammatical_Evolution
EDIT:
Or use this to make it more dynamic
(caution: don't try to find the path by os.path.abspath('./thesis_program') because it may not be always possible that you find your test_files and your thesis_folder are in the same dir; if you can fix them permanently in your code like above; then you are free to use them from anywhere on your system)
import os, sys
lib_path = os.path.abspath('./thesis_program')
sys.path.insert(0,lib_path)