Python importing a module from a parallel directory - python

How would I organize my python imports so that I can have a directory like this.
project
| \
| __init__.py
|
src
| \
| __init__.py
| classes.py
|
test
\
__init__.py
tests.py
And then inside /project/test/tests.py be able to import classes.py
I've got code looking like this in tests.py
from .. src.classes import(
scheduler
db
)
And am getting errors of
SystemError: Parent module '' not loaded, cannot perform relative import
Anyone know what to do?

Python adds the folder containing the script you launch to the PYTHONPATH, so if you run
python test/tests.py
Only the folder test is added to the path (not the base dir that you're executing the command in).
Instead run your tests like so:
python -m test.tests
This will add the base dir to the python path, and then classes will be accessible via a non-relative import:
from src.classes import etc
If you really want to use the relative import style, then your 3 dirs need to be added to a package directory
package
* __init__.py
* project
* src
* test
And you execute it from above the package dir with
python -m package.test.tests
See also:
https://docs.python.org/2/using/cmdline.html
http://www.stereoplex.com/blog/understanding-imports-and-pythonpath

Related

Unable to run python package stand-alone and nested under another repoistory

I created a python package which I use for brain preprocessing - named bpt. I would also like to use the same package as a sub-module in another project named brain_seg.
As a results, I am having problems with import statements which either results in errors when running the package stand-alone or nested.
The structure of the bpt package is as follows:
bpt
|--__init__.py
|--module1.py
|--module2.py
|--run.py
Import statements in the file run.py look something like:
import os
import module1
import module2
.
.
.
The structure of the brain_seg package is as follows:
brain_seg
|--bpt
| |--__init__.py
| |--module1.py
| |--module2.py
| |--run.py
|
|--package2
| |--__init__.py
| |--module1a.py
|
|--__init__.py
When running the run.py script which is part of the stand alone bpt package, everything runs as expected.
If I try to run the same script as part of the brain_seg package, the following error is dispatched:
ModuleNotFoundError: No module named 'module1'
I tried to use relative imports so the nested project will work as expected, resulting in the following run.py file:
import os
from . import module1
from . import module2
.
.
.
Following the change, execution of the brain_seg project worked as expected but when I tried to call the run.py script from the stand alone bpt package, it resulted in the following error being dispatched:
ImportError: attempted relative import with no known parent package
How should I handle the imports such that both options will be supported?
Imports in bpt.run must be absolute or relative:
from bpt.module1 import ... # absolute
from .module1 import ... # relative
To run bpt.run from your repository root with your pythonpath getting correctly set, use -m:
python bpt/run.py # bad
python -m bpt.run # good
If brain_seg is not truly meant to be a package itself, but just a project consisting of multiple packages and modules, get rid of brain_seg/__init__.py.
If you do mean to use it as a package, then move it below the repo root, i.e.
- README.md (etc.)
- .gitignore (etc.)
- brain_seg
- __init__.py
- bps
- __init__.py
- main.py
and use e.g. python -m brain_seg.bps.run
from the repository root.
If you also intend to use bps as a standalone thing, I wouldn't recommend keeping it in the brain_seg hierarchy at all, but to make it pip installable (see https://packaging.python.org/tutorials/packaging-projects/) and then pip install -e ../somewhere/bps to have pip set up an editable link between your projects.

How to import modules from adjacent package without setting PYTHONPATH

I have a python 2.7 project which I have structured as below:
project
|
|____src
| |
| |__pkg
| |
| |__ __init__.py
|
|____test
|
|__test_pkg
| |
| |__ __init__.py
|
|__helpers
| |
| |__ __init__.py
|
|__ __init__.py
I am setting the src folder to the PYTHONPATH, so importing works nicely in the packages inside src. I am using eclipse, pylint inside eclipse and nosetests in eclipse as well as via bash and in a make file (for project). So I have to satisfy lets say every stakeholder!
The problem is importing some code from the helpers package in test. Weirdly enough, my test is also a python package with __init__.py containing some top level setUp and tearDown method for all tests. So when I try this:
import helpers
from helpers.blaaa import Blaaa
in some module inside test_pkg, all my stakeholders are not satisfied. I get the ImportError: No module named ... and pylint also complains about not finding it. I can live with pylint complaining in test folders but nosetests is also dying if I run it in the project directory and test directory. I would prefer not to do relative imports with dot (.).
The problem is that you can not escape the current directory by importing from ..helpers.
But if you start your test code inside the test directory with
python3 -m test_pkg.foo
the current directory will be the test directory and importing helpers will work. On the minus side that means you have to import from . inside test_pkg.

import a file from another location - python

There are two folders , each contain a python file .
For example: first_folder contains a.py & second_folder contains b.py
I tried importing b.py in a.py
But i got not Import error.
ImportError: No module named b
Pls help me to solve this. I also tried creating a blank init.py in both folders, but it did not worked.
Folder structure:
/home/user/scripts/
|
|--------python_scripts
| |
| |
| |------- a.py
|
|--------lib
|
|-------b.py
Suppose you have files like this
.
├── first_folder
│ └── a.py
└── second_folder
└── b.py
You can use abs path to import a.py as a module in b.py
import importlib.util
spec = importlib.util.spec_from_file_location('a', 'path/to/first_folder/a.py')
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
print(dir(foo))
There is another convenient way to load b.py
$ cd path/to/second_folder
$ ln -s path/to/first_folder ./first_folder
and import a.py as a normal python module
import a from first_folder
Python's import is going to look for the modules (.py files) in the python path. You can see what is in python path in the sys.path variable.
By default, sys.path will include directory where the script you ran is located. It will also include everything defined in the PYTHONPATH environment variable.
So, if you have two directories with .py files, you can either put both in python path, or you can make sure everything all of your source is under the same path entry.
Option 1
(this syntax depends on your shell, here it is for windows)
set PYTHONPATH=%PYTHONPATH%;\path\to\second_folder
python \path\to\first_folder\a.py
Then, you can simply import b.
Option 2
Create an empty __init__.py in both directories and a run.py in the directory above them, so you have:
root_dir
run.py
first_folder
__init__.py
a.py
sedond_folder
__init__.py
b.py
Make run.py your entry point (run python run.py) and then you can import any of the modules from any other module using their full module names:
import first_folder.a
import second_folder.b
If the files are in the same directory type this
Import .other_file

how to import from parallel directory in pycharm with python 2.7

I get a directory like the following:
__init__.py
common
| \
| __init__.py
| util.py
|
sites
\
__init__.py
site_a.py
The folder where 'common' and 'sites' locat is named 'father'
I'd like to import common/util.py from inside sites/site_a.py.
I tried to use: from father.common import util
But pycharm reports: unsolved reference 'father'
How shall I import util.py from inside site_a.py?
PS: I don't want to change my PYTHONPATH setting, so please use correct python codes only.

Running Python on a module with relative imports from another directory

Say that under /path/to/foo I have package with a python module:
/path/to/foo:
| my_package
| __init__.py
| my_module.py
| my_other_package
| __init__.py
| my_other_module.py
The file my_module.py does a relative import of my_other_module.py as follows:
from ..my_other_package import my_other_module
I understand that I can do the following from the shell:
> cd /path/to/foo
> python -m my_package.my_module
But what if I don't want to change my current directory? Is there any way to run my module from the shell without having to change PYTHONPATH?
I tried the following:
python -m /path/to/foo/my_package.my_module
but that didn't work. I got: Import by filename is not supported.
Get the relative path:
base_path = os.path.abspath('../my_other_package/') #or any relative directory
append this to the system path (only temporary, will be deleted after execution):
sys.path.append(base_path)
import the file you need in that path:
import my_other_module.py
I believe it you may need a file named __init__.py (with nothing in it) if you wanted to import the file as import directory.file (correct me if I'm wrong).
This thread shows alternate approaches.

Categories