Import from different directories in python - python

This is my folder structure:
src/
__init__py
Lowlevel/
__init__.py
ModuleToCheck.Py
Test/
__init__.py
ModuleToCheck_test.py
(__init__.py are empty files)
Now I want to import ModuleToCheck.py in ModuleToCheck_test.py
How am I able to do this without appending anything to sys.path?
Update:
from ..Lowlevel import ModuleToCheck leads to:
src$ python Test/ModuleToCheck_test.py
Traceback (most recent call last):
File "Test/ModuleToCheck_test.py", line 6, in <module>
from ..Lowlevel import ModuleToCheck
ValueError: Attempted relative import in non-package

The following is from http://docs.python.org/tutorial/modules.html#intra-package-references
Note that both explicit and implicit
relative imports are based on the name
of the current module. Since the name
of the main module is always
"__main__", modules intended for use
as the main module of a Python
application should always use absolute
imports.
You're running your module ModuleToCheck_test.py as the main module, hence the exception.
One solution is to create a test.py module in your src directory containing the following:
import Test.ModuleToCheck_test
You can then run that module using python test.py

Related

How to fix relative import error in python without code change?

In python I have a folder with three files
- __init__.py
- module.py
- test_module.py
in which the module module.py is imported inside the file test_module.py as follows:
from . import module
Of course, when I just run test_module.py I get an error
> python test_module.py
Traceback (most recent call last):
File "test_module.py", line 4, in <module>
from . import module
ImportError: attempted relative import with no known parent package
But as I set the PYTHONPATH to the absolute path to where I am working in
export PYTHONPATH=`pwd`
I expect the import to work (as I did set the PYTHONPATH). But to my surprise I get the same error!
So can I fix the relative import error without any code change?
Since the directory you describe (let's call it thatdirectory) is a package, as marked by an __init__ file, you can "fix" that by cding a directory higher up, then running
python -m thatdirectory.test_module
since running modules with -m fixes up sys.path in a way that makes this particular configuration work.
(In general, any code that messes with sys.path manually, or requires changes to PYTHONPATH to work, is broken in my eyes...)

Why do I have to use a relative import in a package's __init__.py?

Setup
test/
main.py
pkg/
a.py
__init__.py
main.py contains:
import pkg
pkg.a
__init__.py contains:
from . import a
main.py can be run without errors.
Question
Changing the content of __init__.py to
import a
gives the following error when running main.py:
Traceback (most recent call last):
File "C:/Users/me/PycharmProjects/test/main.py", line 1, in <module>
import pkg
File "C:\Users\me\PycharmProjects\test\pkg\__init__.py", line 1, in <module>
import a
ModuleNotFoundError: No module named 'a'
Interestingly, __init__.py can be executed directly with python __init__.py without errors.
What's going on?
When you run a python script, it's parent folder is added to sys.path
run main.py: sys.path[0] = '../test'
run init.py: sys.path[0] = '../test/pkg'
Your case: You try to "absolute-like" import a in __init__.py but the parent folder of a.py - which is '../test/pkg' - is not in the sys.path when you run main.py. This is why you get an error. However, your absolute import is incomplete as it should always start at the top level folder, e.g.
from test.pkg import a
Final answer to your question: You don't have to use relative imports!
See: PEP-8: Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as when a directory inside a package ends up on sys.path).
And keep in mind that relative imports don't work in a top-level-script when __name__ = "__main__", but from imported modules only.
You can learn more about absolute and relative imports here:
Absolute vs. explicit relative import of Python module
https://realpython.com/absolute-vs-relative-python-imports/
I suppose you are using Pycharm? Then that's one of the confusion cause.
For example, let's say your directory looks like this
project1
p1.py
test/
__init__.py
main.py
pkg/
a.py
__init__.py
If you run (F10) the main.py your default working directory will be project1/test, which does not contain the a.py so import a will not find anything.
But if you run (F10) the pkg/__init__.py your working directory will be project1/test/pkg which has the a.py, and it works like what you tested.
So in these situation, if you use from . import a it will look for the directory that file is, project1/test/pkg in this case, which will always work regardless your working directory.

Import error with unit tests: "No module named ..." from local libary

I'm new to Python (JS developer) and am trying to run a testing suite. My project folder structure is as such:
project/
__init__.py
libs/
__init__.py
s3panda.py
tests
__init__.py
tests_s3panda.py
In terminal, I'm running python tests_s3panda.py.
I don't understand how it's unable to find a local module:
Traceback (most recent call last): File "tests_s3panda.py", line 7,
in
from libs.s3panda import S3Panda ImportError: No module named libs.s3panda
tests_s3panda.py snippet:
from __future__ import absolute_import
import unittest
import pandas as pd
from libs.s3panda import S3Panda
class TestS3Panda(unittest.TestCase):
...
Doing from ..libs.s3panda import S3Panda for relative path, I get:
ValueError: Attempted relative import in non-package
I believe the fact that there is no init.py in the top-level folder means that Python is not aware that libs and tests are both part of the same module called project.
Try adding an __init__.py to your project folder, then write the import statement as from project.libs.s3panda import S3Panda. In general, you want to specify absolute imports rather than relative imports (When to use absolute imports).

How to import package modules from in-package "main" module

My package structure is:
main.py
mapp/
__init__.py
core/
__init__.py
tobeimported.py
test/
__init__.py
(test modules)
utils/
__init__.py
blasttofasta.py
The file blasttofasta.py is executed as script.
blasttofasta.py looks like:
import mapp.core.tobeimported
def somefunc():
pass
if __name__ == '__main__':
pass
But Exception occurs:
Traceback (most recent call last):
File "utils/blasttofasta.py", line 5, in <module>
import mapp.core.tobeimported
ImportError: No module named mapp.core.analyzers
How to import tobeimported module? I run the blasttofasta.py from top directory (where main.py is)
EDIT: Maybe better question is: How to get mapp package to the sys.path? Because script file only see its own directory but not the package directory.
Thank you
If I want to including blasttofasta.py or run it as script simultaneously mos important is to have directory containing mapp package in sys.path.
This worked for me:
Before importing mapp (or other module from this package) I wrote into blasttofasta.py:
import os
os.sys.path.append(os.path.dirname(os.path.realpath(__file__))+ '/../../')
This append mapp package path and I can run it as script. On the other side is no problem with is included in another package.
Follow the absolute structure to import.
To import blasttofasta.py in tobeimport.py
ToBeimport contents
from myapp.utils import blasttofasta
Your structure is good.
Two things need to happen:
Your map directory needs a __init__.py file.
You can simply do this (naively):
$ touch /path/to/map/__init__.py
/path/to/map needs to be in sys.path
Please read: http://docs.python.org/2/tutorial/modules.html for more details.

When automatically importing modules from a subfolder, their imports fail

I've read through a couple of similar questions, notably this one about imp.load_module which seems to be close to what I want, but I can't understand why I'm still getting ImportErrors. Here is my folder hierarchy:
program\
__init__.py
main.py
thirdparty\
__init__.py
css\
__init__.py
css.py
utils\
__init__.py
http.py
In main.py I have the following code. This is intended to search the thirdparty\ directory and load each module it finds. Each module is in its own separate directory.
import os
import imp
for root, dirs, files in os.walk("thirdparty"):
for source in (s for s in files if s.endswith(".py")):
name = os.path.splitext(os.path.basename(source))[0]
m = imp.load_module(name, *imp.find_module(name, [root]))
The problem is that css.py happens to use its own subfolder that it loads stuff off of, utils. It has a line in it that says:
from utils import http
And that is where it fails. I get this error when I run main.py.
Traceback (most recent call last):
File "main.py", line 7, in <module>
m = imp.load_module(name, *imp.find_module(name, [root]))
File "thirdparty/css/css.py", line 1, in <module>
from utils import http
ImportError: No module named utils
I'm stumped. css.py is self contained in its own folder, and when I run css.py separately it imports utils just fine. What is causing this?
Maybe you can solve this by changing the import to:
from .utils import http
Or by adding the folder you import to the Python Path:
sys.path.append(os.path.join(root, source))
When you import modules in thirdparty, the place Python looks for modules is still the main directory. The initial import works, because you give the right path to imp.find_module, but after that Python has no idea where to look for the modules.

Categories

Resources