I try to understand how to split up python files belonging to the same project in different directories. If I understood it right I need to use packages as described here in the documentation.
So my structure looks like this:
.
├── A
│ ├── fileA.py
│ └── __init__.py
├── B
│ ├── fileB.py
│ └── __init__.py
└── __init__.py
with empty __init__.py files and
$ cat A/fileA.py
def funA():
print("hello from A")
$ cat B/fileB.py
from A.fileA import funA
if __name__ == "__main__":
funA()
Now I expect that when I execute B/fileB.py I get "Hello from A", but instead I get the following error:
ModuleNotFoundError: No module named 'A'
What am I doing wrong?
Your problem is the same as: Relative imports for the billionth time
TL;DR: you can't do relative imports from the file you execute since
main module is not a part of a package.
As main:
python B/fileB.py
Output:
Traceback (most recent call last):
File "p2/m2.py", line 1, in <module>
from p1.m1 import funA
ImportError: No module named p1.m1
As a module (not main):
python -m B.fileB
Output:
hello from A
One way to solve this is to add module A into the path of fileB.py by adding
import sys
sys.path.insert(0, 'absolute/path/to/A/')
to the top of fileB.py.
Related
I have this file structure
.
└── sample
├── one
│ ├── __init__.py
│ └── util.py
└── two
├── __init__.py
└── test.py
Here is the content of util.py
def isOk():
return True
Here is the content of test.py
from sample.one import util
Whenever I'm inside the [two] folder and I type
python test.py
I get
Traceback (most recent call last):
File "test.py", line 1, in <module>
from sample.one import util
ModuleNotFoundError: No module named 'sample'
How is that possible when I create all folders and __init__.py by the book?
It seems that a method to invoke it might be
python -m two.test
If one and two are both subpackages of sample, then you should add a sample/__init__.py which may be empty.
If you then invoke python -m sample.two.test from the right directory, it should work.
You could even add package-relative imports like this:
# test.py
from ..one import util
Please add the dir path to your PYTHONPATH
export PYTHONPATH=/PATH/TO/DIR/WHICH/CONTAINS/SAMPLE
2 real nice links to go through are:
https://docs.python.org/3/tutorial/modules.html
https://docs.python.org/3/reference/import.html
I'm looking for a way to import a subpackage from within a package in Python 3.
Consider the following structure :
├── main.py
└── package
├── subpackage
│ └── hello.py
└── test.py
What I would like to do is use a function that inside hello.py from within test.py (which is launched by main.py)
main.py
from package.test import print_hello
print_hello()
package/test.py
from subpackage.hello import return_hello
def print_hello():
print(return_hello())
package/subpackage/hello.py
def return_hello():
return "Hello"
But I'm getting the following error :
Traceback (most recent call last):
File ".\main.py", line 1, in <module>
from package.test import print_hello
File "D:\Python\python-learning\test\package\test.py", line 1, in <module>
from subpackage.hello import return_hello
ModuleNotFoundError: No module named 'subpackage'
I tried putting a . in test.py and it worked, but my linter does not like it.
What am I doing wrong ?
edit : I managed to use an absolute path as recommended but now when I try to put everything in a subfolder pylint is not able to import.
└── src
├── main.py
└── package
├── subpackage
│ └── hello.py
└── test.py
Just use
from .subpackage.hello import return_hello
instead of
from subpackage.hello import return_hello
in your test.py file and read this guide for better understanding how imports works in python.
You can see fixed result here : https://repl.it/#ent1c3d/SoupySadUnderstanding
I am using python 2:
python --version
Python 2.7.13 :: Continuum Analytics, Inc.
I have the following project structure:
.
└── foo
├── bar1
│ ├── __init__.py
│ └── mod1.py
├── bar2
│ ├── __init__.py
│ └── mod2.py
├── __init__.py
└── start.py
start.py
from foo.bar2.mod2 import mod2_f
mod2_f()
mod1.py
def mod1_f():
print "mod1_f"
mod2.py
from foo.bar1.mod1 import mod1_f
def mod2_f():
mod1_f()
print "mod2_f"
If I run start.py from an IDE things work ok.
However using something like this:
python ./foo/start.py
results in
Traceback (most recent call last):
File "./foo/start.py", line 1, in <module>
from foo.bar2.mod2 import mod2_f
ImportError: No module named foo.bar2.mod2
Now, let's say I change the imports to
start.py
from bar2.mod2 import mod2_f
mod2_f()
mod2.py
from bar1.mod1 import mod1_f
def mod2_f():
mod1_f()
print "mod2_f"
Now things work from the command line python ./foo/start
However, PyCharm complains. why these differences?
foo is the directory which contains everything, including start.py
So when from start.py you do this
from foo.bar2.mod2 import mod2_f
python looks for a foo module (foo is a module because it contains __init__.py), which too high in your directory structure. I suppose it works from the IDE because IDE adds every module directory to pythonpath. But not from command line it doesn't.
simple fix since bar2 is a directory at the same level as start.py:
from bar2.mod2 import mod2_f
note that from works differently in python 3. See ImportError on python 3, worked fine on python 2.7, that's probably why PyCharm complains when fixing the import line. You should configure PyCharm so it uses Python 2 and not Python 3 for it to work, or just drop the from syntax altogether and do:
import bar2.mod2.mod2_f
I'm currently writing a web application in python that needs unit tests, however whenever I try to import a child module that's in another parent directory I get the following error:
$ python my_package/tests/main.py
Traceback (most recent call last):
File "my_package/tests/test.py", line 1, in <module>
from my_package.core.main import hello
ImportError: No module named my_package.core.main
File: my_package/core/main.py
hello = "Hello"
File: my_package/test/test.py
from my_package.core.main import hello
print(hello, "world!")
My directory structure:
$ tree
.
└── my_package
├── __init__.py
├── core
│ ├── __init__.py
│ └── main.py
└── tests
├── __init__.py
└── test.py
Could someone please explain what I'm doing wrong? Thank you for your time.
It is considered an anti-pattern to modify sys.path. If you want your package to be available to all subpackages, it's better to use setup.py development mode.
Create setup.py in the root of your project:
from setuptools import setup
setup(
name="you_project",
version="0.0.0",
packages=['my_package', ],
install_requires=['requirement1', 'requirement2'],
)
Then run:
$python setup.py develop
After this you will be able to import my_packege from anywhere within your Python environment.
Your my_package is not in PYTHONPATH. At the top of your test.py add the below. Note that any change in location of test.py would affect package_path
from os.path import dirname, abspath
import sys
package_path = dirname(dirname(abspath(__file__)))
sys.path.append(package_path)
I'm trying to build a Python program with the "structure" shown at the end.
The problem is that actions should be able to be executed as scripts as well (I've already included a main in them). When I try to execute DummyAction.py imports keep complaining they can't find misc.
How can I use DummyAction.py as a script and still use the functions in utils.py?
DummyAction.py contains a class called DummyActionClass, and the same for DummyTrigger.py. In utils.py there are several functions that both actions and triggers use and MMD.py contains the main.
/MMD
├── __init__.py
├── MMD.py
├── /actions
│ ├── __init__.py
│ ├── DummyAction.py
├── /misc
│ ├── __init__.py
│ ├── utils.py
└── /triggers
├── DummyTrigger.py
└── __init__.py
The import in DummyAction.py and DummyTrigger.py is:
from misc import utils
And the error is:
File "DDM/actions/DummyAction.py", line 11, in <module>
from misc import utils
ImportError: No module named misc
Seen the updated question, I think the problem is that you should do the import including the root of your dependecies tree: MMD.
So they should all look like:
from MMD.misc import utils
And also you need to call python with the -m option:
python -m MMD.actions.DummyAction
Edit: You said that MMD.py contains the main but it can't be your executable, and that's because is a module (is inside a directory with an __init__.py file). MMD is like your library so you need the executable to be outside and use such library.
You can find [here] some guidelines on how to organize your project.
If you can change you project structure I'll suggest to do it like this:
MMD/
├── runner.py
└── mmd
├── __init__.py
├── main.py
├── /actions
│ ├── __init__.py
│ ├── DummyAction.py
├── /misc
│ ├── __init__.py
│ ├── utils.py
└── /triggers
├── DummyTrigger.py
└── __init__.py
Then in any file inside the mmd directory every import should start with mmd, for example:
from mmd.misc import utils
from mmd.actions import DummyActions
And you put your main code that now is inside MMD.py inside a Main class in main.py, with something like:
# main.py
from mmd.misc import utils
class Main:
def start_session(self):
utils.function()
# etc ...
And then in runner.py you do something like:
# runner.py
from mmd.main import Main
cli = Main()
cli.start_session()
This way inside the MMD directory calling python runner.py you would execute your code, and you can also make executable runner.py so a simply ./runner.py will run your code.
And run your module with:
python -m mmd.actions.DummyAction
I'd do it like this, becasue this way is open to future implementation (and is almost like in the line guides).
If instead you can't, then you can give it a try at removing __init__.py from the MMD directory.
I assume this is a directory structure you're talking about, in which case python doesn't know where to look for utils.py - it tries the local directory, a few places in the path then gives up. It's simple enough to modify the path:
import sys
sys.path.append("/MMD/misc")
import utils
and you should be away.
I've found a "workarround"
try:
#When executing from the main
from misc import utils
except:
#When executing as a standalone script
from MMD.misc import utils
that allows to:
Call the module as a script (while using other modules): python -m MMD.actions.DummyAction
Call the main program and use the module: python MMD/MMD.py
Although I'm not sure if it's strictly correct to use a try - except block with an import, so feel free to add comments or other solutions.
The complete solution would be:
MMD.main
from misc import utils
from actions import DummyAction
class MMD():
def __init__(self):
a = DummyAction.DummyActionClass()
utils.foo()
if __name__ == '__main__':
d = MMD()
Then in actions/DummyAction.py:
try:
#When executing from the main
from misc import utils
except:
#When executing as a standalone script
from MMD.misc import utils
class DummyActionClass():
def __init__(self):
utils.foo()
if __name__ == '__main__':
a = DummyActionClass()
And finally in misc/utils.py:
def foo():
print "Foo was called"