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
Related
I'm trying to use prettyconf - https://github.com/osantana/prettyconf - to use a .env file.
I created a config.py file and put it in the same folder of my script.
My config.py is this one:
from prettyconf import config
class Settings:
ENVIRONMENT = config(
'ENVIRONMENT',
default='dev',
cast=config.option({'dev': 'dev', 'int': 'int', 'prod': 'prod'}),
)
LOG_LEVEL = config('LOG_LEVEL', default='INFO')
settings = Settings()
In my script I import my config.py in this way:
from cl_uploader.config import settings
But I got this error msg:
Traceback (most recent call last):
File "cl_uploader.py", line 7, in <module>
from cl_uploader.config import settings
File "/home/myfolder/Doing/folder/cl_uploader/cl_uploader.py", line 7, in <module>
from cl_uploader.config import settings
ModuleNotFoundError: No module named 'cl_uploader.config'; 'cl_uploader' is not a package
I tried to change to a relative path like this:
from .config import settings
But I got this error:
Traceback (most recent call last):
File "cl_uploader.py", line 7, in <module>
from .config import settings
ImportError: attempted relative import with no known parent package
But if a let like this:
from config import settings
It works! But...
My tests starts to break and I get this msg:
____________________________ ERROR collecting tests/test_cl_uploader.py _____________________________
ImportError while importing test module '/home/myfolder/Doing/folder/tests/test_cl_uploader.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../../.cache/pypoetry/virtualenvs/cl-uploader-12nYBdPj-py3.8/lib/python3.8/site-packages/_pytest/python.py:511: in _importtestmodule
mod = self.fspath.pyimport(ensuresyspath=importmode)
../../.cache/pypoetry/virtualenvs/cl-uploader-12nYBdPj-py3.8/lib/python3.8/site-packages/py/_path/local.py:704: in pyimport
__import__(modname)
../../.cache/pypoetry/virtualenvs/cl-uploader-12nYBdPj-py3.8/lib/python3.8/site-packages/_pytest/assertion/rewrite.py:152: in exec_module
exec(co, module.__dict__)
tests/test_cl_uploader.py:10: in <module>
from cl_uploader.cl_uploader import check_stack_exists
cl_uploader/cl_uploader.py:7: in <module>
from config import settings
E ModuleNotFoundError: No module named 'config'
====================================== short test summary info ======================================
ERROR tests/test_cl_uploader.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================= 1 error in 0.25s ==========================================
My tree folder is set this way:
.
├── cl_uploader
│ ├── cl_uploader.py
│ ├── config.py
│ ├── __init__.py
│ └── resources
│ └── teste.yaml
├── file.tmp
├── local.env
├── Makefile
├── poetry.lock
├── pyproject.toml
├── README.md
└── tests
├── __init__.py
└── test_cl_uploader.py
You are already in the cl_uploader folder. Try: from config import settings.
In __init__.py add this:
import os, sys
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
Then, all files in this directory will be on sys.path. Might want to change the filename to cl_config.py to avoid conflicts.
Your package is called cl_uploader and you have a module cl_uploader within this package. Avoid this duplication of names.
By default python will look in the current working directory first if it can find the module or package, before going through other places.
So when you are inside the cl_uploader folder, it will pickup the cl_uploader module instead of the package. If you are outside it will pickup the package.
In summary: rename cl_uploader.py to something else and everything will work fine.
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 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.
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)