Python packages: relative imports - python

I'm working on a Python application consisting of a core and multiple independent modules using the core. I'm having difficulty setting up relative imports of packages.
app
|- __init__.py
|- core
|- __init__.py
|- corefile.py
|- module1
|- __init__.py
|- main.py
The __init__.py files are empty. I'm running Python 2.7.1.
main.py
from .core import *
Running python main.py results in ValueError: Attempted relative import in non-package.
Similar questions: Ultimate answer to relative python imports, How to do relative imports in Python?, Relative imports in Python
Thanks for the help.

In short, you can only use relative imports from packages that are, themselves, imported.
For example, if you had:
$ cat run.py
from app.module1 import main
main.main()
$ python run.py
Then you could use a relative import in app/module1/main.py (although it would need to be from ..core import foo, because core/ is one level above main.py).

import sys
abs_filepath = '/home/n/Documents/IMPORTANT/deep_learning/drori_2018/ final_proj/Ryans_branch/StackGAN/'
# insert your absolute filepath above as abs_filepath = '/path/to/targ/dir'
sys.path.append(abs_filepath)
Please correct it if there are problems with doing the import this way
Other Answers:
Also please see here for a thorough answer about what's going on.

Related

"ModuleNotFoundError" when importing modules inside package

I am trying to make my own package so that I can use the files in a different folder. This package contains a few different modules and then the main module that imports all the others inside it. For example:
Folder
|- main.py
|- other.py
|- something.py
|- __init__.py
Inside the main.py I have the imports:
import other
import something
and it works just fine when running the file itself; however, I added the __init__.py file and tried to import it into a different folder. The package is recognized, but the main.py gives me the following error:
Exception has occurred: ModuleNotFoundError No module named
'univariate'
File "C:...\stats.py", line 8, in
import univariate
File "F:...\testing.py", line 7, in
from stats import stats
For clarification, the actual main file is called stats.py. This is my first experience trying to make a package so I might be missing something. Thank you.
You need to change your imports into relative imports
import .other
import .something
or to change it to absolute imports rooted to your project folder
import x.y.other
import x.y.something
you can read here about the imports
When you have a module that you're trying to import you don't need the ".py" part.
Having a folder with a init.py file (even a blank one) means that a project that contains that folder can import from it.
/myproject
| - /mymodule
| - |- stats.py
| - |- other.py
| - |- something.py
| - |- __init__.py
| - main.py
then in main.py all you need to do is import mymodule or from mymodule import stats
I always hate to FTFM someone, but here's a link to how to build packages from the official documentation. But, where this really starts to shine is when you need to package your module so that someone else can run it Digital Ocean has a pretty good tutorial here.

ImportError: attempted relative import with no known parent package :(

I'm attempting to import a script from my Items file but I keeps on getting an error
from .Items.Quest1_items import *
gives
from .Items.Quest1_items import *
# ImportError: attempted relative import with no known parent package
# Process finished with exit code 1
Here my project tree, I'm running the script from the main.py file
Quest1/
|
|- main.py
|
|- Items/
| |- __init__.py
| |- Quest1_items.py
Remove the dot from the beginning. Relative paths with respect to main.py are found automatically.
from Items.Quest1_items import *
You can only perform relative import (ie., starting with a dot), inside a package that you import. For instance, imagine the situation:
project/
├ main.py
├ mylib/
├ __init__.py
│ ├ module1.py
│ └ module2.py
in main.py, you would have import mylib or from mylib import *,
but inside module1.py, you could have from . import module2, because here the . stands for mylib (which is a python package, because you imported it within main.py).
So, the solution is simply remove the dot, it's not useful in your situation.
To put it simply: if you use relative import, you can run the file you want to run with 'python -m your_module_path' on the two layers above the outermost file used by your code.
Like the following, if you want to run run.py, you need to go to two layers above it, then run python -m dir1.dir2.run(without .py).
.../dir1/dir2/
-test
-test1.py
from .test2 import *
-test2.py
-run.py
from .test.test1 import *

Import error using relative import syntax

I have a project structured like so:
/proj
main.py
config/
__init__.py
setup.py
gui/
__init__.py
app.py
The program is run by calling python main.py.
In main.py I have from gui import App.
In gui/__init__.py I have from .app import App.
Lastly, in app.py I have from ..config import configure; this throws a ValueError that reads attempted relative import beyond top-level package. To resolve this, I can alter the strucure:
/proj
main.py
proj/
config/
__init__.py
setup.py
gui/
__init__.py
app.py
But then I have to change the import statments to include proj (i.e. from proj.gui import App). Is it possible to use relative imports in the former case with the current structure? If not, how can I import what I need from the config subpackage?
As strange as it sounds, you can do :
from config import configure
in app.py, for your former case (current structure), because when you run python main.py, it interprets config as the next level package, and .. won't work.
(Btw, I think there is lots of room for Python imports to improve. The current PEP 328 is confusing at best).

Importing module with custom lookup

I have some problems with my project structure.
Because of historical reasons project looks like this:
Source/
__init__.py
module1/
__init__.py
script1.py
module2/
__init__.py
script2.py
and in production it deploys like this
server/
__init__.py
module1/
__init__.py
script1.py
module2/
__init__.py
script2.py
The problem is that script2.py has such imports:
from server.module1.script1 import something
Is it possible to say python to search server.*** not in server/*** but in Source/***?
Right now I made this with symlinks, but it looks ugly
You can always add keys to the sys.modules dictionary; these act as aliases for the module:
import sys
try:
import server
except ImportError:
import Source
sys.modules['server'] = Source
Once server is an entry in sys.modules, any sub-modules and packages will be found as well as the server entry will be used as a starting point for further imports.

How to accomplish relative import in python

stuff/
__init__.py
mylib.py
Foo/
__init__.py
main.py
foo/
__init__.py
script.py
script.py wants to import mylib.py
This is just an example, but really I just want to do a relative import of a module in a parent directory. I've tried various things and get this error...
Attempted relative import beyond toplevel package
I read somewhere that the script from where the program starts shouldn't in the package, and I tried modifying the structure for that like so...
stuff/
mylib.py
foo.py // equivalent of main.py in above
foo/
__init__.py
script.py
but got same error.
How can I accomplish this? Is this even an adequate approach?
Edit: In Python 2
After fiddling with it a bit more, I realized how to set it up, and for the sake of specificity I won't use foo bar names. My project directory is set up as...
tools/
core/
object_editor/
# files that need to use ntlib.py
editor.py # see example at bottom
__init__.py
state_editor/
# files that need to use ntlib.py
__init__.py
ntlib.py
__init__.py # core is the top level package
LICENSE
state_editor.py # equivalent to main.py for the state editor
object_editor.py # equivalent to main.py for the object editor
A line in object_editor.py looks like...
from core.object_editor import editor
A line in editor.py looks like...
from .. import ntlib
or alternatively
from core import ntlib
The key is that in the example I gave in the question, the "main" script was being run from within the package. Once I moved it out, created a specific package (core), and moved the library I wanted the editors to share (ntlib) into that package, everything was hunky-dory.
though as long "stuff" is not in your python PATH you got no choice than adding the path.
If you know the level of your script.py from stuff you can do for example:
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
I'm running Python 3.4.2 on Windows 7 and tore my hair out over this.
When running either of these:
python -m unittest
python -m unittest discover
...I would get the 'Attempted relative import beyond toplevel package' error.
For me, the solution was dropping the ".." in my [test_stock.py].
The line was:
from ..stock import Stock
Changed it to:
from stock import Stock
.. and it works.
Folder structure:
C:\
|
+-- stock_alerter
|
+-- __init__.py
+-- stock.py
|
\-- tests
|
+-- __init__.py
\-- test_stock.py
From the PEP it appears that you cannot use a relative import to import a file that is not packaged.
So you would need to add a __init__.py to stuff and change your imports to something like from .mylib import *
However, the PEP seems to make no allowance to keep mylib packaged up in a module. So you might be required to change how you call your library functions.
Another alternative is to move mylib into a subpackage and import it as from .libpackage import mylib
If you're on Linux or perhaps a similar *nix, you can hack this with symlinks.
stuff/
mylib.py
foo.py // equivalent of main.py in above
foo/
script.py
mylib.py -> ../mylib.py
foo2/
script2.py
mylib.py -> ../mylib.py
This is likely not a good pattern to follow.
In my case I opted for it because I had multiple executables dependent on the same library that needed to be put into separate directories.
Implementation of new executable tests shouldn't require the test writer to have a deep understanding of python imports.
tests/
common/
commonlib.py
test1/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py
test2/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py

Categories